Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 0 additions & 68 deletions packages/playwright-cloudflare/src/cloudflare/chunking.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
import { AsyncLocalStorage } from 'async_hooks';

import { chunksToMessage, messageToChunks } from './chunking';

import type { ConnectionTransport, ProtocolRequest, ProtocolResponse } from 'playwright-core/lib/server/transport';

// stores the endpoint and options for client -> server communication
export const transportZone = new AsyncLocalStorage<WebSocketTransport>();

export class WebSocketTransport implements ConnectionTransport {
private _ws: WebSocket;
private _pingInterval: NodeJS.Timer;
private _chunks: Uint8Array[] = [];
onmessage?: (message: ProtocolResponse) => void;
onclose?: () => void;
readonly sessionId: string;
Expand All @@ -24,36 +20,25 @@ export class WebSocketTransport implements ConnectionTransport {
}

constructor(ws: WebSocket, sessionId: string) {
this._pingInterval = setInterval(() => {
return this._ws.send('ping');
}, 1000); // TODO more investigation
this._ws = ws;
this.sessionId = sessionId;
this._ws.addEventListener('message', event => {
this._chunks.push(new Uint8Array(event.data as ArrayBuffer));
const message = chunksToMessage(this._chunks, sessionId);
if (message && this.onmessage)
this.onmessage!(JSON.parse(message) as ProtocolResponse);
this.onmessage?.(JSON.parse(event.data) as ProtocolResponse);
});
this._ws.addEventListener('close', () => {
clearInterval(this._pingInterval as NodeJS.Timeout);
if (this.onclose)
this.onclose();
this.onclose?.();
});
this._ws.addEventListener('error', e => {
// eslint-disable-next-line no-console
console.error(`Websocket error: SessionID: ${sessionId}`, e);
clearInterval(this._pingInterval as NodeJS.Timeout);
});
}

send(message: ProtocolRequest): void {
for (const chunk of messageToChunks(JSON.stringify(message)))
this._ws.send(chunk);
this._ws.send(JSON.stringify(message));
}

close(): void {
clearInterval(this._pingInterval as NodeJS.Timeout);
this._ws.close();
this.onclose?.();
}
Expand Down
12 changes: 6 additions & 6 deletions packages/playwright-cloudflare/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,7 @@ const originalConnectOverCDP = playwright.chromium.connectOverCDP;

async function connectDevtools(endpoint: BrowserEndpoint, options: { sessionId: string, persistent?: boolean }): Promise<WebSocket> {
resetMonotonicTime();
const url = new URL(`${HTTP_FAKE_HOST}/v1/connectDevtools`);
url.searchParams.set('browser_session', options.sessionId);
const url = new URL(`${HTTP_FAKE_HOST}/v1/devtools/browser/${options.sessionId}`);
if (options.persistent)
url.searchParams.set('persistent', 'true');
const response = await getBrowserBinding(endpoint).fetch(url, {
Expand All @@ -65,7 +64,9 @@ async function connectDevtools(endpoint: BrowserEndpoint, options: { sessionId:
function extractOptions(endpoint: BrowserEndpoint): { sessionId?: string, keep_alive?: number, persistent?: boolean } {
if (typeof endpoint === 'string' || endpoint instanceof URL) {
const url = endpoint instanceof URL ? endpoint : new URL(endpoint);
const sessionId = url.searchParams.get('browser_session') ?? undefined;
// Support both old format (?browser_session=) and new format (/v1/devtools/browser/:sessionId)
const pathMatch = url.pathname.match(/^\/v1\/devtools\/browser\/([^/]+)$/);
const sessionId = pathMatch?.[1] ?? url.searchParams.get('browser_session') ?? undefined;
const keepAlive = url.searchParams.has('keep_alive') ? parseInt(url.searchParams.get('keep_alive')!, 10) : undefined;
const persistent = url.searchParams.has('persistent');
return { sessionId, keep_alive: keepAlive, persistent };
Expand All @@ -78,10 +79,9 @@ export function endpointURLString(binding: BrowserWorker | BrowserBindingKey, op
if (!bindingKey || !(bindingKey in env))
throw new Error(`No binding found for ${binding}`);

const url = new URL(`${HTTP_FAKE_HOST}/v1/connectDevtools`);
const sessionPath = options?.sessionId ? `/${options.sessionId}` : '';
const url = new URL(`${HTTP_FAKE_HOST}/v1/devtools/browser${sessionPath}`);
url.searchParams.set('browser_binding', bindingKey);
if (options?.sessionId)
url.searchParams.set('browser_session', options.sessionId);
if (options?.persistent)
url.searchParams.set('persistent', 'true');
if (options?.keepAlive)
Expand Down
Loading
Loading