move under own dispatcher
This commit is contained in:
parent
048f6d95cf
commit
10646b1c25
|
|
@ -66,7 +66,6 @@ export const slowMoActions = new Set([
|
|||
|
||||
export const commandsWithTracingSnapshots = new Set([
|
||||
'EventTarget.waitForEventInfo',
|
||||
'LocalUtils.waitForEventInfo',
|
||||
'MockingProxy.waitForEventInfo',
|
||||
'BrowserContext.waitForEventInfo',
|
||||
'Page.waitForEventInfo',
|
||||
|
|
|
|||
|
|
@ -236,7 +236,6 @@ scheme.EventTargetWaitForEventInfoParams = tObject({
|
|||
error: tOptional(tString),
|
||||
}),
|
||||
});
|
||||
scheme.LocalUtilsWaitForEventInfoParams = tType('EventTargetWaitForEventInfoParams');
|
||||
scheme.MockingProxyWaitForEventInfoParams = tType('EventTargetWaitForEventInfoParams');
|
||||
scheme.BrowserContextWaitForEventInfoParams = tType('EventTargetWaitForEventInfoParams');
|
||||
scheme.PageWaitForEventInfoParams = tType('EventTargetWaitForEventInfoParams');
|
||||
|
|
@ -244,7 +243,6 @@ scheme.WebSocketWaitForEventInfoParams = tType('EventTargetWaitForEventInfoParam
|
|||
scheme.ElectronApplicationWaitForEventInfoParams = tType('EventTargetWaitForEventInfoParams');
|
||||
scheme.AndroidDeviceWaitForEventInfoParams = tType('EventTargetWaitForEventInfoParams');
|
||||
scheme.EventTargetWaitForEventInfoResult = tOptional(tObject({}));
|
||||
scheme.LocalUtilsWaitForEventInfoResult = tType('EventTargetWaitForEventInfoResult');
|
||||
scheme.MockingProxyWaitForEventInfoResult = tType('EventTargetWaitForEventInfoResult');
|
||||
scheme.BrowserContextWaitForEventInfoResult = tType('EventTargetWaitForEventInfoResult');
|
||||
scheme.PageWaitForEventInfoResult = tType('EventTargetWaitForEventInfoResult');
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import path from 'path';
|
|||
import os from 'os';
|
||||
import type * as channels from '@protocol/channels';
|
||||
import { ManualPromise } from '../../utils/manualPromise';
|
||||
import { assert, calculateSha1, createGuid, HttpServer, removeFolders, urlMatches } from '../../utils';
|
||||
import { assert, calculateSha1, createGuid, removeFolders } from '../../utils';
|
||||
import type { RootDispatcher } from './dispatcher';
|
||||
import { Dispatcher } from './dispatcher';
|
||||
import { yazl, yauzl } from '../../zipBundle';
|
||||
|
|
@ -41,14 +41,13 @@ import type { Playwright } from '../playwright';
|
|||
import { SdkObject } from '../../server/instrumentation';
|
||||
import { serializeClientSideCallMetadata } from '../../utils';
|
||||
import { deviceDescriptors as descriptors } from '../deviceDescriptors';
|
||||
import { APIRequestContextDispatcher, RequestDispatcher, ResponseDispatcher, RouteDispatcher } from './networkDispatchers';
|
||||
import type { APIRequestContext } from '../fetch';
|
||||
import { GlobalAPIRequestContext } from '../fetch';
|
||||
import { MockingProxy, ServerInterceptionRegistry } from '../mockingProxy';
|
||||
import { MockingProxy } from '../mockingProxy';
|
||||
import { MockingProxyDispatcher } from './mockingProxyDispatcher';
|
||||
|
||||
export class LocalUtilsDispatcher extends Dispatcher<SdkObject, channels.LocalUtilsChannel, RootDispatcher> implements channels.LocalUtilsChannel {
|
||||
_type_LocalUtils: boolean;
|
||||
_type_EventTarget: boolean;
|
||||
private _harBackends = new Map<string, HarBackend>();
|
||||
private _stackSessions = new Map<string, {
|
||||
file: string,
|
||||
|
|
@ -56,9 +55,7 @@ export class LocalUtilsDispatcher extends Dispatcher<SdkObject, channels.LocalUt
|
|||
tmpDir: string | undefined,
|
||||
callStacks: channels.ClientSideCallMetadata[]
|
||||
}>();
|
||||
_requestContext: APIRequestContext;
|
||||
private _interceptionRegistry;
|
||||
private _server?: WorkerHttpServer;
|
||||
private _requestContext: APIRequestContext;
|
||||
|
||||
constructor(scope: RootDispatcher, playwright: Playwright) {
|
||||
const localUtils = new SdkObject(playwright, 'localUtils', 'localUtils');
|
||||
|
|
@ -68,40 +65,9 @@ export class LocalUtilsDispatcher extends Dispatcher<SdkObject, channels.LocalUt
|
|||
const requestContext = new GlobalAPIRequestContext(playwright, {});
|
||||
super(scope, localUtils, 'LocalUtils', {
|
||||
deviceDescriptors,
|
||||
requestContext: APIRequestContextDispatcher.from(scope, requestContext),
|
||||
});
|
||||
this._requestContext = requestContext;
|
||||
this._type_LocalUtils = true;
|
||||
this._type_EventTarget = true;
|
||||
|
||||
this._interceptionRegistry = new ServerInterceptionRegistry(this._object, this._requestContext, {
|
||||
onRequest: request => {
|
||||
this._dispatchEvent('request', { request: RequestDispatcher.from(this.parentScope() as any, request) });
|
||||
},
|
||||
onRequestFinished: (request, response) => {
|
||||
this._dispatchEvent('requestFinished', {
|
||||
request: RequestDispatcher.from(this.parentScope() as any, request),
|
||||
response: ResponseDispatcher.fromNullable(this.parentScope() as any, response ?? null),
|
||||
responseEndTiming: request._responseEndTiming,
|
||||
});
|
||||
},
|
||||
onRequestFailed: request => {
|
||||
this._dispatchEvent('requestFailed', {
|
||||
request: RequestDispatcher.from(this.parentScope() as any, request),
|
||||
responseEndTiming: request._responseEndTiming,
|
||||
failureText: request._failureText ?? undefined
|
||||
});
|
||||
},
|
||||
onResponse: (request, response) => {
|
||||
this._dispatchEvent('response', {
|
||||
request: RequestDispatcher.from(this.parentScope() as any, request),
|
||||
response: ResponseDispatcher.from(this.parentScope() as any, response),
|
||||
});
|
||||
},
|
||||
onRoute: (route, request) => {
|
||||
this._dispatchEvent('route', { route: RouteDispatcher.from(RequestDispatcher.from(this.parentScope() as any, request), route) });
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async zip(params: channels.LocalUtilsZipParams): Promise<void> {
|
||||
|
|
@ -316,24 +282,10 @@ export class LocalUtilsDispatcher extends Dispatcher<SdkObject, channels.LocalUt
|
|||
this._stackSessions.delete(stacksId!);
|
||||
}
|
||||
|
||||
async setServerNetworkInterceptionPatterns(params: channels.LocalUtilsSetServerNetworkInterceptionPatternsParams, metadata?: CallMetadata): Promise<channels.LocalUtilsSetServerNetworkInterceptionPatternsResult> {
|
||||
if (!this._server) {
|
||||
this._server = new WorkerHttpServer();
|
||||
new MockingProxy(this._interceptionRegistry).install(this._server);
|
||||
await this._server.start({ port: params.port });
|
||||
}
|
||||
|
||||
if (params.patterns.length === 0)
|
||||
return this._interceptionRegistry.setRequestInterceptor(undefined);
|
||||
|
||||
const urlMatchers = params.patterns.map(pattern => pattern.regexSource ? new RegExp(pattern.regexSource, pattern.regexFlags!) : pattern.glob!);
|
||||
this._interceptionRegistry.setRequestInterceptor(url => urlMatchers.some(urlMatch => urlMatches(undefined, url, urlMatch)));
|
||||
}
|
||||
}
|
||||
|
||||
export class WorkerHttpServer extends HttpServer {
|
||||
override _handleCORS(request: http.IncomingMessage, response: http.ServerResponse): boolean {
|
||||
return false;
|
||||
async newMockingProxy(params: channels.LocalUtilsNewMockingProxyParams, metadata?: CallMetadata): Promise<channels.LocalUtilsNewMockingProxyResult> {
|
||||
const mockingProxy = new MockingProxy(this._object, this._requestContext);
|
||||
await mockingProxy.start(params.port);
|
||||
return { mockingProxy: MockingProxyDispatcher.from(this.parentScope(), mockingProxy) };
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,27 +14,33 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
import type { CallMetadata } from '@protocol/callMetadata';
|
||||
import type { MockingProxy, ServerInterceptionRegistry } from '../mockingProxy';
|
||||
import type { MockingProxy } from '../mockingProxy';
|
||||
import type { RootDispatcher } from './dispatcher';
|
||||
import { Dispatcher, existingDispatcher } from './dispatcher';
|
||||
import type * as channels from '@protocol/channels';
|
||||
import { SdkObject } from '../instrumentation';
|
||||
import { APIRequestContextDispatcher } from './networkDispatchers';
|
||||
import { urlMatches } from '@isomorphic/urlMatch';
|
||||
|
||||
export class MockingProxyDispatcher extends Dispatcher<ServerInterceptionRegistry, channels.MockingProxyChannel, RootDispatcher> implements channels.MockingProxyChannel {
|
||||
export class MockingProxyDispatcher extends Dispatcher<MockingProxy, channels.MockingProxyChannel, RootDispatcher> implements channels.MockingProxyChannel {
|
||||
_type_MockingProxy = true;
|
||||
_type_EventTarget = true;
|
||||
|
||||
static from(scope: RootDispatcher, mockingProxy: ServerInterceptionRegistry): MockingProxyDispatcher {
|
||||
static from(scope: RootDispatcher, mockingProxy: MockingProxy): MockingProxyDispatcher {
|
||||
return existingDispatcher<MockingProxyDispatcher>(mockingProxy) || new MockingProxyDispatcher(scope, mockingProxy);
|
||||
}
|
||||
|
||||
private constructor(scope: RootDispatcher, mockingProxy: ServerInterceptionRegistry) {
|
||||
private constructor(scope: RootDispatcher, mockingProxy: MockingProxy) {
|
||||
super(scope, mockingProxy, 'MockingProxy', {
|
||||
port: mockingProxy.port(),
|
||||
port: mockingProxy.port,
|
||||
requestContext: APIRequestContextDispatcher.from(scope, mockingProxy.fetchRequest),
|
||||
});
|
||||
}
|
||||
|
||||
setInterceptionPatterns(params: channels.MockingProxySetInterceptionPatternsParams, metadata?: CallMetadata): Promise<channels.MockingProxySetInterceptionPatternsResult> {
|
||||
throw new Error('Method not implemented.');
|
||||
async setInterceptionPatterns(params: channels.MockingProxySetInterceptionPatternsParams, metadata?: CallMetadata): Promise<channels.MockingProxySetInterceptionPatternsResult> {
|
||||
if (params.patterns.length === 0)
|
||||
return this._object.setInterceptionPatterns(undefined);
|
||||
|
||||
const urlMatchers = params.patterns.map(pattern => pattern.regexSource ? new RegExp(pattern.regexSource, pattern.regexFlags!) : pattern.glob!);
|
||||
this._object.setInterceptionPatterns(url => urlMatchers.some(urlMatch => urlMatches(undefined, url, urlMatch)));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,144 +19,45 @@ import https from 'https';
|
|||
import url from 'url';
|
||||
import type { APIRequestContext } from './fetch';
|
||||
import { SdkObject } from './instrumentation';
|
||||
import type { RemoteAddr, RequestContext, ResourceTiming, SecurityDetails } from './network';
|
||||
import type { RequestContext, ResourceTiming, SecurityDetails } from './network';
|
||||
import { Request, Response, Route } from './network';
|
||||
import type { HeadersArray, NormalizedContinueOverrides, NormalizedFulfillResponse } from './types';
|
||||
import { ManualPromise, monotonicTime } from 'playwright-core/lib/utils';
|
||||
import type { WorkerHttpServer } from './dispatchers/localUtilsDispatcher';
|
||||
import type { HeadersArray, } from './types';
|
||||
import { HttpServer, ManualPromise, monotonicTime } from '../utils';
|
||||
import { TLSSocket } from 'tls';
|
||||
import type { AddressInfo } from 'net';
|
||||
import { pipeline } from 'stream/promises';
|
||||
import { Transform } from 'stream';
|
||||
|
||||
type InterceptorResult =
|
||||
| { result: 'continue', request: Request, overrides?: NormalizedContinueOverrides }
|
||||
| { result: 'abort', request: Request, errorCode: string }
|
||||
| { result: 'fulfill', request: Request, response: NormalizedFulfillResponse };
|
||||
|
||||
interface EventDelegate {
|
||||
onRequest(request: Request): void;
|
||||
onRequestFinished(request: Request, response: Response): void;
|
||||
onRequestFailed(request: Request): void;
|
||||
onResponse(request: Request, response: Response): void;
|
||||
onRoute(route: Route, request: Request): void;
|
||||
}
|
||||
|
||||
export class ServerInterceptionRegistry extends SdkObject implements RequestContext {
|
||||
private _eventDelegate: EventDelegate;
|
||||
export class MockingProxy extends SdkObject implements RequestContext {
|
||||
fetchRequest: APIRequestContext;
|
||||
private _matches?: (url: string) => boolean;
|
||||
private _httpServer = new WorkerHttpServer();
|
||||
|
||||
constructor(parent: SdkObject, requestContext: APIRequestContext, eventDelegate: EventDelegate) {
|
||||
super(parent, 'serverInterceptionRegistry');
|
||||
this._eventDelegate = eventDelegate;
|
||||
constructor(parent: SdkObject, requestContext: APIRequestContext) {
|
||||
super(parent, 'MockingProxy');
|
||||
this.fetchRequest = requestContext;
|
||||
}
|
||||
|
||||
setRequestInterceptor(matches?: (url: string) => boolean) {
|
||||
this._matches = matches;
|
||||
}
|
||||
|
||||
handle(url: string, method: string, body: Buffer | null, headers: HeadersArray): Promise<InterceptorResult> {
|
||||
const request = new Request(this, null, null, null, undefined, url, '', method, body, headers);
|
||||
request.setRawRequestHeaders(headers);
|
||||
this._eventDelegate.onRequest(request);
|
||||
|
||||
if (!this._matches?.(url))
|
||||
return Promise.resolve({ result: 'continue', request });
|
||||
|
||||
return new Promise(resolve => {
|
||||
const route = new Route(request, {
|
||||
async abort(errorCode) {
|
||||
resolve({ result: 'abort', request, errorCode });
|
||||
},
|
||||
async continue(overrides) {
|
||||
resolve({ result: 'continue', request, overrides });
|
||||
},
|
||||
async fulfill(response) {
|
||||
resolve({ result: 'fulfill', request, response });
|
||||
},
|
||||
});
|
||||
|
||||
this._eventDelegate.onRoute(route, request);
|
||||
});
|
||||
}
|
||||
|
||||
failed(request: Request, error: string) {
|
||||
request._setFailureText(error);
|
||||
this._eventDelegate.onRequestFailed(request);
|
||||
}
|
||||
|
||||
response(request: Request, status: number, statusText: string, headers: HeadersArray, body: () => Promise<Buffer>, httpVersion: string, timing: ResourceTiming, securityDetails: SecurityDetails | undefined, serverAddr: RemoteAddr | undefined) {
|
||||
const response = new Response(request, status, statusText, headers, timing, body, false, httpVersion);
|
||||
response.setRawResponseHeaders(headers);
|
||||
response._securityDetailsFinished(securityDetails);
|
||||
response._serverAddrFinished(serverAddr);
|
||||
this._eventDelegate.onResponse(request, response);
|
||||
|
||||
return {
|
||||
finished: async (responseEndTiming: number, transferSize: number, encodedBodySize: number) => {
|
||||
response._requestFinished(responseEndTiming);
|
||||
response.setTransferSize(transferSize);
|
||||
response.setEncodedBodySize(encodedBodySize);
|
||||
response.setResponseHeadersSize(transferSize - encodedBodySize);
|
||||
this._eventDelegate.onRequestFinished(request, response);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
addRouteInFlight(route: Route): void {
|
||||
|
||||
}
|
||||
|
||||
removeRouteInFlight(route: Route): void {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function headersArray(req: Pick<http.IncomingMessage, 'headersDistinct'>): HeadersArray {
|
||||
return Object.entries(req.headersDistinct).flatMap(([name, values = []]) => values.map(value => ({ name, value })));
|
||||
}
|
||||
|
||||
function headersArrayToOutgoingHeaders(headers: HeadersArray) {
|
||||
const result: http.OutgoingHttpHeaders = {};
|
||||
for (const { name, value } of headers) {
|
||||
if (result[name] === undefined)
|
||||
result[name] = value;
|
||||
else if (Array.isArray(result[name]))
|
||||
result[name].push(value);
|
||||
else
|
||||
result[name] = [result[name] as string, value];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
async function collectBody(req: http.IncomingMessage) {
|
||||
return await new Promise<Buffer>((resolve, reject) => {
|
||||
const chunks: Buffer[] = [];
|
||||
req.on('data', chunk => chunks.push(chunk));
|
||||
req.on('end', () => resolve(Buffer.concat(chunks)));
|
||||
req.on('error', reject);
|
||||
});
|
||||
}
|
||||
|
||||
export class MockingProxy {
|
||||
private readonly _registry: ServerInterceptionRegistry;
|
||||
|
||||
constructor(registry: ServerInterceptionRegistry) {
|
||||
this._registry = registry;
|
||||
}
|
||||
|
||||
install(server: WorkerHttpServer) {
|
||||
server.routePrefix('/', (req, res) => {
|
||||
this._httpServer.routePrefix('/', (req, res) => {
|
||||
this._proxy(req, res);
|
||||
return true;
|
||||
});
|
||||
server.server().on('connect', (req, socket, head) => {
|
||||
this._httpServer.server().on('connect', (req, socket, head) => {
|
||||
socket.end('HTTP/1.1 405 Method Not Allowed\r\n\r\n');
|
||||
});
|
||||
}
|
||||
|
||||
async start(port?: number): Promise<void> {
|
||||
await this._httpServer.start({ port });
|
||||
}
|
||||
|
||||
get port() {
|
||||
return this._httpServer.port();
|
||||
}
|
||||
|
||||
setInterceptionPatterns(matches?: (url: string) => boolean) {
|
||||
this._matches = matches;
|
||||
}
|
||||
|
||||
private async _proxy(req: http.IncomingMessage, res: http.ServerResponse) {
|
||||
if (req.url?.startsWith('/'))
|
||||
req.url = req.url.substring(1);
|
||||
|
|
@ -170,14 +71,14 @@ export class MockingProxy {
|
|||
delete req.headersDistinct.host;
|
||||
const headers = headersArray(req);
|
||||
const body = await collectBody(req);
|
||||
const result = await this._registry.handle(req.url!, req.method!, body, headers);
|
||||
switch (result.result) {
|
||||
case 'abort': {
|
||||
req.destroy(result.errorCode ? new Error(result.errorCode) : undefined);
|
||||
return;
|
||||
}
|
||||
case 'continue': {
|
||||
const { overrides } = result;
|
||||
const request = new Request(this, null, null, null, undefined, req.url!, '', req.method!, body, headers);
|
||||
request.setRawRequestHeaders(headers);
|
||||
|
||||
const route = new Route(request, {
|
||||
abort: async errorCode => {
|
||||
req.destroy(errorCode ? new Error(errorCode) : undefined);
|
||||
},
|
||||
continue: async overrides => {
|
||||
const proxyUrl = url.parse(overrides?.url ?? req.url!);
|
||||
const httpLib = proxyUrl.protocol === 'https:' ? https : http;
|
||||
const proxyHeaders = overrides?.headers ?? headers;
|
||||
|
|
@ -225,16 +126,11 @@ export class MockingProxy {
|
|||
|
||||
const address = socket.address() as AddressInfo;
|
||||
const responseBodyPromise = new ManualPromise<Buffer>();
|
||||
const response = this._registry.response(
|
||||
result.request,
|
||||
proxyRes.statusCode!,
|
||||
proxyRes.statusMessage!, headersArray(proxyRes),
|
||||
() => responseBodyPromise,
|
||||
proxyRes.httpVersion,
|
||||
timings,
|
||||
securityDetails,
|
||||
{ ipAddress: address.family === 'IPv6' ? `[${address.address}]` : address.address, port: address.port },
|
||||
);
|
||||
const response = new Response(request, proxyRes.statusCode!, proxyRes.statusMessage!, headersArray(proxyRes), timings, () => responseBodyPromise, false, proxyRes.httpVersion);
|
||||
response.setRawResponseHeaders(headers);
|
||||
response._securityDetailsFinished(securityDetails);
|
||||
response._serverAddrFinished({ ipAddress: address.family === 'IPv6' ? `[${address.address}]` : address.address, port: address.port });
|
||||
this.emit('response', response);
|
||||
|
||||
try {
|
||||
res.writeHead(proxyRes.statusCode!, proxyRes.headers);
|
||||
|
|
@ -253,20 +149,24 @@ export class MockingProxy {
|
|||
const body = Buffer.concat(chunks);
|
||||
responseBodyPromise.resolve(body);
|
||||
|
||||
response.finished(
|
||||
monotonicTime() - startAt,
|
||||
socket.bytesRead - socketBytesReadStart,
|
||||
body.byteLength
|
||||
);
|
||||
const transferSize = socket.bytesRead - socketBytesReadStart;
|
||||
const encodedBodySize = body.byteLength;
|
||||
response._requestFinished(monotonicTime() - startAt);
|
||||
response.setTransferSize(transferSize);
|
||||
response.setEncodedBodySize(encodedBodySize);
|
||||
response.setResponseHeadersSize(transferSize - encodedBodySize);
|
||||
this.emit('requestFinished', response);
|
||||
resolve();
|
||||
} catch (error) {
|
||||
this._registry.failed(result.request, error.toString());
|
||||
request._setFailureText('' + error);
|
||||
this.emit('failed', request);
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
|
||||
proxyReq.on('error', error => {
|
||||
this._registry.failed(result.request, error.toString());
|
||||
request._setFailureText('' + error);
|
||||
this.emit('failed', request);
|
||||
res.statusCode = 502;
|
||||
res.end(resolve);
|
||||
});
|
||||
|
|
@ -283,19 +183,51 @@ export class MockingProxy {
|
|||
});
|
||||
proxyReq.end(proxyBody);
|
||||
});
|
||||
}
|
||||
case 'fulfill': {
|
||||
const { response: { status, headers, body, isBase64 } } = result;
|
||||
},
|
||||
fulfill: async ({ status, headers, body, isBase64 }) => {
|
||||
res.statusCode = status;
|
||||
for (const { name, value } of headers)
|
||||
res.appendHeader(name, value);
|
||||
res.sendDate = false;
|
||||
res.end(Buffer.from(body, isBase64 ? 'base64' : 'utf-8'));
|
||||
return;
|
||||
}
|
||||
default: {
|
||||
throw new Error('Unexpected result');
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
if (this._matches?.(req.url!))
|
||||
this.emit('route', { route, request });
|
||||
else
|
||||
await route.continue({ isFallback: false });
|
||||
}
|
||||
}
|
||||
|
||||
function headersArray(req: Pick<http.IncomingMessage, 'headersDistinct'>): HeadersArray {
|
||||
return Object.entries(req.headersDistinct).flatMap(([name, values = []]) => values.map(value => ({ name, value })));
|
||||
}
|
||||
|
||||
function headersArrayToOutgoingHeaders(headers: HeadersArray) {
|
||||
const result: http.OutgoingHttpHeaders = {};
|
||||
for (const { name, value } of headers) {
|
||||
if (result[name] === undefined)
|
||||
result[name] = value;
|
||||
else if (Array.isArray(result[name]))
|
||||
result[name].push(value);
|
||||
else
|
||||
result[name] = [result[name] as string, value];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
async function collectBody(req: http.IncomingMessage) {
|
||||
return await new Promise<Buffer>((resolve, reject) => {
|
||||
const chunks: Buffer[] = [];
|
||||
req.on('data', chunk => chunks.push(chunk));
|
||||
req.on('end', () => resolve(Buffer.concat(chunks)));
|
||||
req.on('error', reject);
|
||||
});
|
||||
}
|
||||
|
||||
export class WorkerHttpServer extends HttpServer {
|
||||
override _handleCORS(request: http.IncomingMessage, response: http.ServerResponse): boolean {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,10 +89,10 @@ export function stripFragmentFromUrl(url: string): string {
|
|||
}
|
||||
|
||||
export interface RequestContext extends SdkObject {
|
||||
addRouteInFlight(route: Route): void;
|
||||
removeRouteInFlight(route: Route): void;
|
||||
|
||||
fetchRequest: APIRequestContext;
|
||||
|
||||
addRouteInFlight?(route: Route): void;
|
||||
removeRouteInFlight?(route: Route): void;
|
||||
}
|
||||
|
||||
export class Request extends SdkObject {
|
||||
|
|
@ -261,7 +261,7 @@ export class Route extends SdkObject {
|
|||
super(request._frame || request._context, 'route');
|
||||
this._request = request;
|
||||
this._delegate = delegate;
|
||||
this._request._context.addRouteInFlight(this);
|
||||
this._request._context.addRouteInFlight?.(this);
|
||||
}
|
||||
|
||||
request(): Request {
|
||||
|
|
@ -347,7 +347,7 @@ export class Route extends SdkObject {
|
|||
}
|
||||
|
||||
private _endHandling() {
|
||||
this._request._context.removeRouteInFlight(this);
|
||||
this._request._context.removeRouteInFlight?.(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
2
packages/protocol/src/channels.d.ts
vendored
2
packages/protocol/src/channels.d.ts
vendored
|
|
@ -455,7 +455,7 @@ export type LocalUtilsInitializer = {
|
|||
};
|
||||
export interface LocalUtilsEventTarget {
|
||||
}
|
||||
export interface LocalUtilsChannel extends LocalUtilsEventTarget, EventTargetChannel {
|
||||
export interface LocalUtilsChannel extends LocalUtilsEventTarget, Channel {
|
||||
_type_LocalUtils: boolean;
|
||||
zip(params: LocalUtilsZipParams, metadata?: CallMetadata): Promise<LocalUtilsZipResult>;
|
||||
harOpen(params: LocalUtilsHarOpenParams, metadata?: CallMetadata): Promise<LocalUtilsHarOpenResult>;
|
||||
|
|
|
|||
|
|
@ -551,8 +551,6 @@ EventTarget:
|
|||
LocalUtils:
|
||||
type: interface
|
||||
|
||||
extends: EventTarget
|
||||
|
||||
initializer:
|
||||
deviceDescriptors:
|
||||
type: array
|
||||
|
|
|
|||
Loading…
Reference in a new issue