test-wuying-agentbay-sdk
Version:
TypeScript SDK for interacting with the Wuying AgentBay cloud runtime environment
349 lines (289 loc) • 14.3 kB
text/typescript
/**
* Browser Context Cookie Persistence Example (TypeScript)
*
* This example demonstrates how to use Browser Context to persist cookies
* across multiple sessions in TypeScript. It shows the complete workflow of:
* 1. Creating a session with Browser Context
* 2. Setting cookies in the browser
* 3. Deleting the session with context synchronization
* 4. Creating a new session with the same Browser Context
* 5. Verifying that cookies persist across sessions
*/
import { AgentBay, newCreateSessionParams, BrowserOptionClass, BrowserContext } from 'wuying-agentbay-sdk';
import { chromium } from 'playwright';
async function main(): Promise<void> {
// Get API key from environment
const apiKey = process.env.AGENTBAY_API_KEY;
if (!apiKey) {
console.error("Error: AGENTBAY_API_KEY environment variable not set");
return;
}
// Initialize AgentBay client
const agentBay = new AgentBay({ apiKey });
console.log("AgentBay client initialized");
// Create a unique context name for this demo
const contextName = `browser-cookie-demo-${Date.now()}`;
try {
// Step 1: Create or get a persistent context for browser data
console.log(`Step 1: Creating context '${contextName}'...`);
const contextResult = await agentBay.context.get(contextName, true);
if (!contextResult.success || !contextResult.context) {
console.log(`Failed to create context: ${contextResult.errorMessage}`);
return;
}
const context = contextResult.context;
console.log(`Context created with ID: ${context.id}`);
// Step 2: Create first session with Browser Context
console.log("Step 2: Creating first session with Browser Context...");
const browserContext = new BrowserContext(context.id, true);
const params = newCreateSessionParams()
.withImageId("browser_latest") // Browser image ID
.withBrowserContext(browserContext);
const sessionResult = await agentBay.create(params);
if (!sessionResult.success || !sessionResult.session) {
console.log(`Failed to create first session: ${sessionResult.errorMessage}`);
return;
}
const session1 = sessionResult.session;
console.log(`First session created with ID: ${session1.sessionId}`);
// Step 3: Initialize browser and set cookies with enhanced error handling
console.log("Step 3: Initializing browser and setting test cookies...");
// Initialize browser with retry logic
console.log("Initializing browser...");
const browserOptions = new BrowserOptionClass();
const initSuccess = await session1.browser.initializeAsync(browserOptions);
if (!initSuccess) {
console.log("❌ Failed to initialize browser");
return;
}
console.log("✅ Browser initialized successfully");
// Wait a moment for browser to be fully ready
await new Promise(resolve => setTimeout(resolve, 2000));
// Get endpoint URL with validation
const endpointUrl = await session1.browser.getEndpointUrl();
console.log(`Raw endpoint URL: ${JSON.stringify(endpointUrl)}`);
if (!endpointUrl) {
console.log("❌ Failed to get browser endpoint URL - browser may not be ready");
return;
}
if (!endpointUrl.startsWith('ws://') && !endpointUrl.startsWith('wss://')) {
console.log(`❌ Invalid endpoint URL format: ${endpointUrl}`);
console.log("Expected WebSocket URL starting with ws:// or wss://");
return;
}
console.log(`✅ Browser endpoint URL obtained: ${endpointUrl}`);
// Test data
const testUrl = "https://www.aliyun.com";
const testDomain = "aliyun.com";
// Define test cookies
const testCookies = [
{
name: "demo_cookie_1",
value: "demo_value_1",
domain: testDomain,
path: "/",
httpOnly: false,
secure: false,
expires: Math.floor(Date.now() / 1000) + 3600 // 1 hour from now
},
{
name: "demo_cookie_2",
value: "demo_value_2",
domain: testDomain,
path: "/",
httpOnly: false,
secure: false,
expires: Math.floor(Date.now() / 1000) + 3600 // 1 hour from now
}
];
// Connect with Playwright with enhanced error handling
let browser, cdpSession;
try {
console.log("Attempting to connect via CDP...");
browser = await chromium.connectOverCDP(endpointUrl);
console.log("✅ Successfully connected to browser via CDP");
} catch (error) {
console.log(`❌ Failed to connect via CDP: ${error}`);
console.log("This could be due to:");
console.log("1. Network connectivity issues");
console.log("2. Browser process not fully ready");
console.log("3. Firewall blocking WebSocket connections");
console.log("4. Invalid endpoint URL format");
// Try to get more information about the session
console.log("Session details for debugging:");
console.log(`Session ID: ${session1.sessionId}`);
console.log(`Endpoint URL: ${endpointUrl}`);
return;
}
try {
cdpSession = await browser.newBrowserCDPSession()
const contextP = browser.contexts()[0] || await browser.newContext();
const page = await contextP.newPage();
// Navigate to test URL first (required before setting cookies)
console.log(`Navigating to ${testUrl}...`);
await page.goto(testUrl);
console.log(`✅ Successfully navigated to ${testUrl}`);
await page.waitForTimeout(2000);
// Add test cookies
await contextP.addCookies(testCookies);
console.log(`✅ Added ${testCookies.length} test cookies`);
// Verify cookies were set
const cookies = await contextP.cookies();
const cookieDict: Record<string, string> = {};
cookies.forEach((cookie: any) => {
if (cookie.name) {
cookieDict[cookie.name] = cookie.value || '';
}
});
console.log(`Total cookies in first session: ${cookies.length}`);
// Check our test cookies
for (const testCookie of testCookies) {
const cookieName = testCookie.name;
if (cookieName in cookieDict) {
console.log(`✓ Test cookie '${cookieName}' set successfully: ${cookieDict[cookieName]}`);
} else {
console.log(`✗ Test cookie '${cookieName}' not found`);
}
}
await cdpSession.send('Browser.close')
console.log("First session browser operations completed")
// Wait for browser to save cookies to file
console.log("Waiting for browser to save cookies to file...")
await new Promise(resolve => setTimeout(resolve, 2000));
console.log("Wait completed")
await browser.close()
console.log("First session browser operations completed")
} finally {
if (browser) {
await browser.close();
console.log("✅ Browser connection closed");
}
}
console.log("First session browser operations completed");
// Step 4: Delete first session with context synchronization
console.log("Step 4: Deleting first session with context synchronization...");
const deleteResult = await agentBay.delete(session1, true); // syncContext = true
if (!deleteResult.success) {
console.log(`Failed to delete first session: ${deleteResult.errorMessage}`);
return;
}
console.log(`First session deleted successfully (RequestID: ${deleteResult.requestId})`);
// Wait for context sync to complete
console.log("Waiting for context synchronization to complete...");
await new Promise(resolve => setTimeout(resolve, 3000));
// Step 5: Create second session with same Browser Context
console.log("Step 5: Creating second session with same Browser Context...");
const sessionResult2 = await agentBay.create(params);
if (!sessionResult2.success || !sessionResult2.session) {
console.log(`Failed to create second session: ${sessionResult2.errorMessage}`);
return;
}
const session2 = sessionResult2.session;
console.log(`Second session created with ID: ${session2.sessionId}`);
// Step 6: Verify cookie persistence
console.log("Step 6: Verifying cookie persistence in second session...");
// Initialize browser in second session
const initSuccess2 = await session2.browser.initializeAsync(new BrowserOptionClass());
if (!initSuccess2) {
console.log("Failed to initialize browser in second session");
return;
}
console.log("Second session browser initialized successfully");
// Wait for browser to be ready
await new Promise(resolve => setTimeout(resolve, 2000));
// Get endpoint URL for second session
const endpointUrl2 = await session2.browser.getEndpointUrl();
if (!endpointUrl2) {
console.log("Failed to get browser endpoint URL for second session");
return;
}
console.log(`Second session browser endpoint URL: ${endpointUrl2}`);
// Check cookies in second session with error handling
let browser2;
try {
browser2 = await chromium.connectOverCDP(endpointUrl2);
let context2;
if (browser2.contexts().length > 0) {
context2 = await browser2.contexts()[0];
} else {
context2 = await browser2.newContext();
}
// Read cookies directly from context (without opening any page)
const cookies2 = await context2.cookies();
const cookieDict2: Record<string, string> = {};
cookies2.forEach((cookie: any) => {
console.log(`Cookie name: ${cookie.name}, value: ${cookie.value}`);
if (cookie.name) {
cookieDict2[cookie.name] = cookie.value || '';
}
});
console.log(`Total cookies in second session: ${cookies2.length}`);
// Check if our test cookies persisted
const expectedCookieNames = new Set(["demo_cookie_1", "demo_cookie_2"]);
const foundCookieNames = new Set(Object.keys(cookieDict2));
console.log("Found cookie names:", foundCookieNames);
console.log("Checking cookie persistence...");
const missingCookies = [...expectedCookieNames].filter(name => !foundCookieNames.has(name));
if (missingCookies.length > 0) {
console.log(`✗ Missing test cookies: ${missingCookies.join(', ')}`);
console.log("Cookie persistence test FAILED");
} else {
// Verify cookie values
let allValuesMatch = true;
for (const testCookie of testCookies) {
const cookieName = testCookie.name;
const expectedValue = testCookie.value;
const actualValue = cookieDict2[cookieName] || "";
if (expectedValue === actualValue) {
console.log(`✓ Cookie '${cookieName}' persisted correctly: ${actualValue}`);
} else {
console.log(`✗ Cookie '${cookieName}' value mismatch. Expected: ${expectedValue}, Actual: ${actualValue}`);
allValuesMatch = false;
}
}
if (allValuesMatch) {
console.log("🎉 Cookie persistence test PASSED! All cookies persisted correctly across sessions.");
} else {
console.log("Cookie persistence test FAILED due to value mismatches");
}
}
} catch (error) {
console.log(`❌ Failed to connect to second session browser: ${error}`);
} finally {
if (browser2) {
await browser2.close();
console.log("Second session browser operations completed");
}
}
// Step 7: Clean up second session
console.log("Step 7: Cleaning up second session...");
const deleteResult2 = await agentBay.delete(session2);
if (deleteResult2.success) {
console.log(`Second session deleted successfully (RequestID: ${deleteResult2.requestId})`);
} else {
console.log(`Failed to delete second session: ${deleteResult2.errorMessage}`);
}
} catch (error) {
console.log(`❌ Error during demo: ${error}`);
console.log("\nDebugging information:");
console.log(`Error type: ${typeof error}`);
console.log(`Error message: ${error instanceof Error ? error.message : String(error)}`);
if (error instanceof Error && error.stack) {
console.log(`Error stack: ${error.stack}`);
}
} finally {
// Clean up context
try {
const contextResult = await agentBay.context.get(contextName, false);
if (contextResult.success && contextResult.context) {
await agentBay.context.delete(contextResult.context);
console.log(`Context '${contextName}' deleted`);
}
} catch (error) {
console.log(`Warning: Failed to delete context: ${error}`);
}
}
console.log("\nBrowser Context Cookie Persistence Demo completed!");
}
// Run the example
main().catch(console.error);