mirror of
https://github.com/puppeteer/puppeteer
synced 2024-06-14 14:02:48 +00:00
chore(webdriver): support priority for request interception (#12191)
This commit is contained in:
parent
59bffce972
commit
08bc8542ea
@ -10,7 +10,7 @@ Aborts a request.
|
|||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
class HTTPRequest {
|
class HTTPRequest {
|
||||||
abstract abort(errorCode?: ErrorCode, priority?: number): Promise<void>;
|
abort(errorCode?: ErrorCode, priority?: number): Promise<void>;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ The most recent reason for aborting the request
|
|||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
class HTTPRequest {
|
class HTTPRequest {
|
||||||
abstract abortErrorReason(): Protocol.Network.ErrorReason | null;
|
abortErrorReason(): Protocol.Network.ErrorReason | null;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ Continues request with optional request overrides.
|
|||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
class HTTPRequest {
|
class HTTPRequest {
|
||||||
abstract continue(
|
continue(
|
||||||
overrides?: ContinueRequestOverrides,
|
overrides?: ContinueRequestOverrides,
|
||||||
priority?: number
|
priority?: number
|
||||||
): Promise<void>;
|
): Promise<void>;
|
||||||
|
@ -10,7 +10,7 @@ The `ContinueRequestOverrides` that will be used if the interception is allowed
|
|||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
class HTTPRequest {
|
class HTTPRequest {
|
||||||
abstract continueRequestOverrides(): ContinueRequestOverrides;
|
continueRequestOverrides(): ContinueRequestOverrides;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ Adds an async request handler to the processing queue. Deferred handlers are not
|
|||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
class HTTPRequest {
|
class HTTPRequest {
|
||||||
abstract enqueueInterceptAction(
|
enqueueInterceptAction(
|
||||||
pendingHandler: () => void | PromiseLike<unknown>
|
pendingHandler: () => void | PromiseLike<unknown>
|
||||||
): void;
|
): void;
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ Awaits pending interception handlers and then decides how to fulfill the request
|
|||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
class HTTPRequest {
|
class HTTPRequest {
|
||||||
abstract finalizeInterceptions(): Promise<void>;
|
finalizeInterceptions(): Promise<void>;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ InterceptResolutionAction is one of: `abort`, `respond`, `continue`, `disabled`,
|
|||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
class HTTPRequest {
|
class HTTPRequest {
|
||||||
abstract interceptResolutionState(): InterceptResolutionState;
|
interceptResolutionState(): InterceptResolutionState;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ Is `true` if the intercept resolution has already been handled, `false` otherwis
|
|||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
class HTTPRequest {
|
class HTTPRequest {
|
||||||
abstract isInterceptResolutionHandled(): boolean;
|
isInterceptResolutionHandled(): boolean;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ Fulfills a request with the given response.
|
|||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
class HTTPRequest {
|
class HTTPRequest {
|
||||||
abstract respond(
|
respond(
|
||||||
response: Partial<ResponseForRequest>,
|
response: Partial<ResponseForRequest>,
|
||||||
priority?: number
|
priority?: number
|
||||||
): Promise<void>;
|
): Promise<void>;
|
||||||
|
@ -10,7 +10,7 @@ The `ResponseForRequest` that gets used if the interception is allowed to respon
|
|||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
class HTTPRequest {
|
class HTTPRequest {
|
||||||
abstract responseForRequest(): Partial<ResponseForRequest> | null;
|
responseForRequest(): Partial<ResponseForRequest> | null;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ import type {Protocol} from 'devtools-protocol';
|
|||||||
|
|
||||||
import type {ProtocolError} from '../common/Errors.js';
|
import type {ProtocolError} from '../common/Errors.js';
|
||||||
import {debugError} from '../common/util.js';
|
import {debugError} from '../common/util.js';
|
||||||
|
import {assert} from '../util/assert.js';
|
||||||
|
|
||||||
import type {CDPSession} from './CDPSession.js';
|
import type {CDPSession} from './CDPSession.js';
|
||||||
import type {Frame} from './Frame.js';
|
import type {Frame} from './Frame.js';
|
||||||
@ -120,6 +121,29 @@ export abstract class HTTPRequest {
|
|||||||
*/
|
*/
|
||||||
_redirectChain: HTTPRequest[] = [];
|
_redirectChain: HTTPRequest[] = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
protected interception: {
|
||||||
|
enabled: boolean;
|
||||||
|
handled: boolean;
|
||||||
|
handlers: Array<() => void | PromiseLike<any>>;
|
||||||
|
resolutionState: InterceptResolutionState;
|
||||||
|
requestOverrides: ContinueRequestOverrides;
|
||||||
|
response: Partial<ResponseForRequest> | null;
|
||||||
|
abortReason: Protocol.Network.ErrorReason | null;
|
||||||
|
} = {
|
||||||
|
enabled: false,
|
||||||
|
handled: false,
|
||||||
|
handlers: [],
|
||||||
|
resolutionState: {
|
||||||
|
action: InterceptResolutionAction.None,
|
||||||
|
},
|
||||||
|
requestOverrides: {},
|
||||||
|
response: null,
|
||||||
|
abortReason: null,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Warning! Using this client can break Puppeteer. Use with caution.
|
* Warning! Using this client can break Puppeteer. Use with caution.
|
||||||
*
|
*
|
||||||
@ -142,18 +166,27 @@ export abstract class HTTPRequest {
|
|||||||
* if the interception is allowed to continue (ie, `abort()` and
|
* if the interception is allowed to continue (ie, `abort()` and
|
||||||
* `respond()` aren't called).
|
* `respond()` aren't called).
|
||||||
*/
|
*/
|
||||||
abstract continueRequestOverrides(): ContinueRequestOverrides;
|
continueRequestOverrides(): ContinueRequestOverrides {
|
||||||
|
assert(this.interception.enabled, 'Request Interception is not enabled!');
|
||||||
|
return this.interception.requestOverrides;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `ResponseForRequest` that gets used if the
|
* The `ResponseForRequest` that gets used if the
|
||||||
* interception is allowed to respond (ie, `abort()` is not called).
|
* interception is allowed to respond (ie, `abort()` is not called).
|
||||||
*/
|
*/
|
||||||
abstract responseForRequest(): Partial<ResponseForRequest> | null;
|
responseForRequest(): Partial<ResponseForRequest> | null {
|
||||||
|
assert(this.interception.enabled, 'Request Interception is not enabled!');
|
||||||
|
return this.interception.response;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The most recent reason for aborting the request
|
* The most recent reason for aborting the request
|
||||||
*/
|
*/
|
||||||
abstract abortErrorReason(): Protocol.Network.ErrorReason | null;
|
abortErrorReason(): Protocol.Network.ErrorReason | null {
|
||||||
|
assert(this.interception.enabled, 'Request Interception is not enabled!');
|
||||||
|
return this.interception.abortReason;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An InterceptResolutionState object describing the current resolution
|
* An InterceptResolutionState object describing the current resolution
|
||||||
@ -166,13 +199,23 @@ export abstract class HTTPRequest {
|
|||||||
* InterceptResolutionAction is one of: `abort`, `respond`, `continue`,
|
* InterceptResolutionAction is one of: `abort`, `respond`, `continue`,
|
||||||
* `disabled`, `none`, or `already-handled`.
|
* `disabled`, `none`, or `already-handled`.
|
||||||
*/
|
*/
|
||||||
abstract interceptResolutionState(): InterceptResolutionState;
|
interceptResolutionState(): InterceptResolutionState {
|
||||||
|
if (!this.interception.enabled) {
|
||||||
|
return {action: InterceptResolutionAction.Disabled};
|
||||||
|
}
|
||||||
|
if (this.interception.handled) {
|
||||||
|
return {action: InterceptResolutionAction.AlreadyHandled};
|
||||||
|
}
|
||||||
|
return {...this.interception.resolutionState};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is `true` if the intercept resolution has already been handled,
|
* Is `true` if the intercept resolution has already been handled,
|
||||||
* `false` otherwise.
|
* `false` otherwise.
|
||||||
*/
|
*/
|
||||||
abstract isInterceptResolutionHandled(): boolean;
|
isInterceptResolutionHandled(): boolean {
|
||||||
|
return this.interception.handled;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds an async request handler to the processing queue.
|
* Adds an async request handler to the processing queue.
|
||||||
@ -180,15 +223,51 @@ export abstract class HTTPRequest {
|
|||||||
* but they are guaranteed to resolve before the request interception
|
* but they are guaranteed to resolve before the request interception
|
||||||
* is finalized.
|
* is finalized.
|
||||||
*/
|
*/
|
||||||
abstract enqueueInterceptAction(
|
enqueueInterceptAction(
|
||||||
pendingHandler: () => void | PromiseLike<unknown>
|
pendingHandler: () => void | PromiseLike<unknown>
|
||||||
): void;
|
): void {
|
||||||
|
this.interception.handlers.push(pendingHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
abstract _abort(
|
||||||
|
errorReason: Protocol.Network.ErrorReason | null
|
||||||
|
): Promise<void>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
abstract _respond(response: Partial<ResponseForRequest>): Promise<void>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
abstract _continue(overrides: ContinueRequestOverrides): Promise<void>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Awaits pending interception handlers and then decides how to fulfill
|
* Awaits pending interception handlers and then decides how to fulfill
|
||||||
* the request interception.
|
* the request interception.
|
||||||
*/
|
*/
|
||||||
abstract finalizeInterceptions(): Promise<void>;
|
async finalizeInterceptions(): Promise<void> {
|
||||||
|
await this.interception.handlers.reduce((promiseChain, interceptAction) => {
|
||||||
|
return promiseChain.then(interceptAction);
|
||||||
|
}, Promise.resolve());
|
||||||
|
this.interception.handlers = []; // TODO: verify this is correct top let gc run
|
||||||
|
const {action} = this.interceptResolutionState();
|
||||||
|
switch (action) {
|
||||||
|
case 'abort':
|
||||||
|
return await this._abort(this.interception.abortReason);
|
||||||
|
case 'respond':
|
||||||
|
if (this.interception.response === null) {
|
||||||
|
throw new Error('Response is missing for the interception');
|
||||||
|
}
|
||||||
|
return await this._respond(this.interception.response);
|
||||||
|
case 'continue':
|
||||||
|
return await this._continue(this.interception.requestOverrides);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains the request's resource type as it was perceived by the rendering
|
* Contains the request's resource type as it was perceived by the rendering
|
||||||
@ -326,10 +405,42 @@ export abstract class HTTPRequest {
|
|||||||
*
|
*
|
||||||
* Exception is immediately thrown if the request interception is not enabled.
|
* Exception is immediately thrown if the request interception is not enabled.
|
||||||
*/
|
*/
|
||||||
abstract continue(
|
async continue(
|
||||||
overrides?: ContinueRequestOverrides,
|
overrides: ContinueRequestOverrides = {},
|
||||||
priority?: number
|
priority?: number
|
||||||
): Promise<void>;
|
): Promise<void> {
|
||||||
|
// Request interception is not supported for data: urls.
|
||||||
|
if (this.url().startsWith('data:')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
assert(this.interception.enabled, 'Request Interception is not enabled!');
|
||||||
|
assert(!this.interception.handled, 'Request is already handled!');
|
||||||
|
if (priority === undefined) {
|
||||||
|
return await this._continue(overrides);
|
||||||
|
}
|
||||||
|
this.interception.requestOverrides = overrides;
|
||||||
|
if (
|
||||||
|
this.interception.resolutionState.priority === undefined ||
|
||||||
|
priority > this.interception.resolutionState.priority
|
||||||
|
) {
|
||||||
|
this.interception.resolutionState = {
|
||||||
|
action: InterceptResolutionAction.Continue,
|
||||||
|
priority,
|
||||||
|
};
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (priority === this.interception.resolutionState.priority) {
|
||||||
|
if (
|
||||||
|
this.interception.resolutionState.action === 'abort' ||
|
||||||
|
this.interception.resolutionState.action === 'respond'
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.interception.resolutionState.action =
|
||||||
|
InterceptResolutionAction.Continue;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fulfills a request with the given response.
|
* Fulfills a request with the given response.
|
||||||
@ -363,10 +474,38 @@ export abstract class HTTPRequest {
|
|||||||
*
|
*
|
||||||
* Exception is immediately thrown if the request interception is not enabled.
|
* Exception is immediately thrown if the request interception is not enabled.
|
||||||
*/
|
*/
|
||||||
abstract respond(
|
async respond(
|
||||||
response: Partial<ResponseForRequest>,
|
response: Partial<ResponseForRequest>,
|
||||||
priority?: number
|
priority?: number
|
||||||
): Promise<void>;
|
): Promise<void> {
|
||||||
|
// Mocking responses for dataURL requests is not currently supported.
|
||||||
|
if (this.url().startsWith('data:')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
assert(this.interception.enabled, 'Request Interception is not enabled!');
|
||||||
|
assert(!this.interception.handled, 'Request is already handled!');
|
||||||
|
if (priority === undefined) {
|
||||||
|
return await this._respond(response);
|
||||||
|
}
|
||||||
|
this.interception.response = response;
|
||||||
|
if (
|
||||||
|
this.interception.resolutionState.priority === undefined ||
|
||||||
|
priority > this.interception.resolutionState.priority
|
||||||
|
) {
|
||||||
|
this.interception.resolutionState = {
|
||||||
|
action: InterceptResolutionAction.Respond,
|
||||||
|
priority,
|
||||||
|
};
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (priority === this.interception.resolutionState.priority) {
|
||||||
|
if (this.interception.resolutionState.action === 'abort') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.interception.resolutionState.action =
|
||||||
|
InterceptResolutionAction.Respond;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Aborts a request.
|
* Aborts a request.
|
||||||
@ -382,7 +521,33 @@ export abstract class HTTPRequest {
|
|||||||
* {@link Page.setRequestInterception}. If it is not enabled, this method will
|
* {@link Page.setRequestInterception}. If it is not enabled, this method will
|
||||||
* throw an exception immediately.
|
* throw an exception immediately.
|
||||||
*/
|
*/
|
||||||
abstract abort(errorCode?: ErrorCode, priority?: number): Promise<void>;
|
async abort(
|
||||||
|
errorCode: ErrorCode = 'failed',
|
||||||
|
priority?: number
|
||||||
|
): Promise<void> {
|
||||||
|
// Request interception is not supported for data: urls.
|
||||||
|
if (this.url().startsWith('data:')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const errorReason = errorReasons[errorCode];
|
||||||
|
assert(errorReason, 'Unknown error code: ' + errorCode);
|
||||||
|
assert(this.interception.enabled, 'Request Interception is not enabled!');
|
||||||
|
assert(!this.interception.handled, 'Request is already handled!');
|
||||||
|
if (priority === undefined) {
|
||||||
|
return await this._abort(errorReason);
|
||||||
|
}
|
||||||
|
this.interception.abortReason = errorReason;
|
||||||
|
if (
|
||||||
|
this.interception.resolutionState.priority === undefined ||
|
||||||
|
priority >= this.interception.resolutionState.priority
|
||||||
|
) {
|
||||||
|
this.interception.resolutionState = {
|
||||||
|
action: InterceptResolutionAction.Abort,
|
||||||
|
priority,
|
||||||
|
};
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -517,6 +682,23 @@ export const STATUS_TEXTS: Record<string, string> = {
|
|||||||
'511': 'Network Authentication Required',
|
'511': 'Network Authentication Required',
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
const errorReasons: Record<ErrorCode, Protocol.Network.ErrorReason> = {
|
||||||
|
aborted: 'Aborted',
|
||||||
|
accessdenied: 'AccessDenied',
|
||||||
|
addressunreachable: 'AddressUnreachable',
|
||||||
|
blockedbyclient: 'BlockedByClient',
|
||||||
|
blockedbyresponse: 'BlockedByResponse',
|
||||||
|
connectionaborted: 'ConnectionAborted',
|
||||||
|
connectionclosed: 'ConnectionClosed',
|
||||||
|
connectionfailed: 'ConnectionFailed',
|
||||||
|
connectionrefused: 'ConnectionRefused',
|
||||||
|
connectionreset: 'ConnectionReset',
|
||||||
|
internetdisconnected: 'InternetDisconnected',
|
||||||
|
namenotresolved: 'NameNotResolved',
|
||||||
|
timedout: 'TimedOut',
|
||||||
|
failed: 'Failed',
|
||||||
|
} as const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
|
@ -121,6 +121,7 @@ export class BidiFrame extends Frame {
|
|||||||
request.once('error', () => {
|
request.once('error', () => {
|
||||||
this.page().trustedEmitter.emit(PageEvent.RequestFailed, httpRequest);
|
this.page().trustedEmitter.emit(PageEvent.RequestFailed, httpRequest);
|
||||||
});
|
});
|
||||||
|
void httpRequest.finalizeInterceptions();
|
||||||
});
|
});
|
||||||
|
|
||||||
this.browsingContext.on('navigation', ({navigation}) => {
|
this.browsingContext.on('navigation', ({navigation}) => {
|
||||||
|
@ -48,6 +48,8 @@ export class BidiHTTPRequest extends HTTPRequest {
|
|||||||
super();
|
super();
|
||||||
requests.set(request, this);
|
requests.set(request, this);
|
||||||
|
|
||||||
|
this.interception.enabled = request.isBlocked;
|
||||||
|
|
||||||
this.#request = request;
|
this.#request = request;
|
||||||
this.#frame = frame;
|
this.#frame = frame;
|
||||||
this.id = request.id;
|
this.id = request.id;
|
||||||
@ -60,6 +62,7 @@ export class BidiHTTPRequest extends HTTPRequest {
|
|||||||
#initialize() {
|
#initialize() {
|
||||||
this.#request.on('redirect', request => {
|
this.#request.on('redirect', request => {
|
||||||
this.#redirect = BidiHTTPRequest.from(request, this.#frame);
|
this.#redirect = BidiHTTPRequest.from(request, this.#frame);
|
||||||
|
void this.#redirect.finalizeInterceptions();
|
||||||
});
|
});
|
||||||
this.#request.once('success', data => {
|
this.#request.once('success', data => {
|
||||||
this.#response = BidiHTTPResponse.from(data, this);
|
this.#response = BidiHTTPResponse.from(data, this);
|
||||||
@ -132,33 +135,15 @@ export class BidiHTTPRequest extends HTTPRequest {
|
|||||||
return redirects;
|
return redirects;
|
||||||
}
|
}
|
||||||
|
|
||||||
override enqueueInterceptAction(
|
|
||||||
pendingHandler: () => void | PromiseLike<unknown>
|
|
||||||
): void {
|
|
||||||
// Execute the handler when interception is not supported
|
|
||||||
void pendingHandler();
|
|
||||||
}
|
|
||||||
|
|
||||||
override frame(): BidiFrame | null {
|
override frame(): BidiFrame | null {
|
||||||
return this.#frame ?? null;
|
return this.#frame ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
override continueRequestOverrides(): never {
|
override async _continue(
|
||||||
throw new UnsupportedOperation();
|
|
||||||
}
|
|
||||||
|
|
||||||
override async continue(
|
|
||||||
overrides: ContinueRequestOverrides = {}
|
overrides: ContinueRequestOverrides = {}
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
if (!this.#request.isBlocked) {
|
|
||||||
throw new Error('Request Interception is not enabled!');
|
|
||||||
}
|
|
||||||
// Request interception is not supported for data: urls.
|
|
||||||
if (this.url().startsWith('data:')) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const headers: Bidi.Network.Header[] = getBidiHeaders(overrides.headers);
|
const headers: Bidi.Network.Header[] = getBidiHeaders(overrides.headers);
|
||||||
|
this.interception.handled = true;
|
||||||
|
|
||||||
return await this.#request
|
return await this.#request
|
||||||
.continueRequest({
|
.continueRequest({
|
||||||
@ -173,53 +158,24 @@ export class BidiHTTPRequest extends HTTPRequest {
|
|||||||
headers: headers.length > 0 ? headers : undefined,
|
headers: headers.length > 0 ? headers : undefined,
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
|
this.interception.handled = false;
|
||||||
return handleError(error);
|
return handleError(error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
override responseForRequest(): never {
|
override async _abort(): Promise<void> {
|
||||||
throw new UnsupportedOperation();
|
this.interception.handled = true;
|
||||||
|
return await this.#request.failRequest().catch(error => {
|
||||||
|
this.interception.handled = false;
|
||||||
|
throw error;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
override abortErrorReason(): never {
|
override async _respond(
|
||||||
throw new UnsupportedOperation();
|
|
||||||
}
|
|
||||||
|
|
||||||
override interceptResolutionState(): never {
|
|
||||||
throw new UnsupportedOperation();
|
|
||||||
}
|
|
||||||
|
|
||||||
override isInterceptResolutionHandled(): never {
|
|
||||||
throw new UnsupportedOperation();
|
|
||||||
}
|
|
||||||
|
|
||||||
override finalizeInterceptions(): never {
|
|
||||||
throw new UnsupportedOperation();
|
|
||||||
}
|
|
||||||
|
|
||||||
override async abort(): Promise<void> {
|
|
||||||
if (!this.#request.isBlocked) {
|
|
||||||
throw new Error('Request Interception is not enabled!');
|
|
||||||
}
|
|
||||||
// Request interception is not supported for data: urls.
|
|
||||||
if (this.url().startsWith('data:')) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return await this.#request.failRequest();
|
|
||||||
}
|
|
||||||
|
|
||||||
override async respond(
|
|
||||||
response: Partial<ResponseForRequest>,
|
response: Partial<ResponseForRequest>,
|
||||||
_priority?: number
|
_priority?: number
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
if (!this.#request.isBlocked) {
|
this.interception.handled = true;
|
||||||
throw new Error('Request Interception is not enabled!');
|
|
||||||
}
|
|
||||||
// Request interception is not supported for data: urls.
|
|
||||||
if (this.url().startsWith('data:')) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const responseBody: string | undefined =
|
const responseBody: string | undefined =
|
||||||
response.body && response.body instanceof Uint8Array
|
response.body && response.body instanceof Uint8Array
|
||||||
? response.body.toString('base64')
|
? response.body.toString('base64')
|
||||||
@ -254,17 +210,22 @@ export class BidiHTTPRequest extends HTTPRequest {
|
|||||||
}
|
}
|
||||||
const status = response.status || 200;
|
const status = response.status || 200;
|
||||||
|
|
||||||
return await this.#request.provideResponse({
|
return await this.#request
|
||||||
statusCode: status,
|
.provideResponse({
|
||||||
headers: headers.length > 0 ? headers : undefined,
|
statusCode: status,
|
||||||
reasonPhrase: STATUS_TEXTS[status],
|
headers: headers.length > 0 ? headers : undefined,
|
||||||
body: responseBody
|
reasonPhrase: STATUS_TEXTS[status],
|
||||||
? {
|
body: responseBody
|
||||||
type: 'base64',
|
? {
|
||||||
value: responseBody,
|
type: 'base64',
|
||||||
}
|
value: responseBody,
|
||||||
: undefined,
|
}
|
||||||
});
|
: undefined,
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
this.interception.handled = false;
|
||||||
|
throw error;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,18 +9,14 @@ import type {CDPSession} from '../api/CDPSession.js';
|
|||||||
import type {Frame} from '../api/Frame.js';
|
import type {Frame} from '../api/Frame.js';
|
||||||
import {
|
import {
|
||||||
type ContinueRequestOverrides,
|
type ContinueRequestOverrides,
|
||||||
type ErrorCode,
|
|
||||||
headersArray,
|
headersArray,
|
||||||
HTTPRequest,
|
HTTPRequest,
|
||||||
InterceptResolutionAction,
|
|
||||||
type InterceptResolutionState,
|
|
||||||
type ResourceType,
|
type ResourceType,
|
||||||
type ResponseForRequest,
|
type ResponseForRequest,
|
||||||
STATUS_TEXTS,
|
STATUS_TEXTS,
|
||||||
handleError,
|
handleError,
|
||||||
} from '../api/HTTPRequest.js';
|
} from '../api/HTTPRequest.js';
|
||||||
import {debugError, isString} from '../common/util.js';
|
import {debugError, isString} from '../common/util.js';
|
||||||
import {assert} from '../util/assert.js';
|
|
||||||
|
|
||||||
import type {CdpHTTPResponse} from './HTTPResponse.js';
|
import type {CdpHTTPResponse} from './HTTPResponse.js';
|
||||||
|
|
||||||
@ -34,8 +30,7 @@ export class CdpHTTPRequest extends HTTPRequest {
|
|||||||
|
|
||||||
#client: CDPSession;
|
#client: CDPSession;
|
||||||
#isNavigationRequest: boolean;
|
#isNavigationRequest: boolean;
|
||||||
#allowInterception: boolean;
|
|
||||||
#interceptionHandled = false;
|
|
||||||
#url: string;
|
#url: string;
|
||||||
#resourceType: ResourceType;
|
#resourceType: ResourceType;
|
||||||
|
|
||||||
@ -44,13 +39,6 @@ export class CdpHTTPRequest extends HTTPRequest {
|
|||||||
#postData?: string;
|
#postData?: string;
|
||||||
#headers: Record<string, string> = {};
|
#headers: Record<string, string> = {};
|
||||||
#frame: Frame | null;
|
#frame: Frame | null;
|
||||||
#continueRequestOverrides: ContinueRequestOverrides;
|
|
||||||
#responseForRequest: Partial<ResponseForRequest> | null = null;
|
|
||||||
#abortErrorReason: Protocol.Network.ErrorReason | null = null;
|
|
||||||
#interceptResolutionState: InterceptResolutionState = {
|
|
||||||
action: InterceptResolutionAction.None,
|
|
||||||
};
|
|
||||||
#interceptHandlers: Array<() => void | PromiseLike<any>>;
|
|
||||||
#initiator?: Protocol.Network.Initiator;
|
#initiator?: Protocol.Network.Initiator;
|
||||||
|
|
||||||
override get client(): CDPSession {
|
override get client(): CDPSession {
|
||||||
@ -96,7 +84,6 @@ export class CdpHTTPRequest extends HTTPRequest {
|
|||||||
this.#isNavigationRequest =
|
this.#isNavigationRequest =
|
||||||
data.requestId === data.loaderId && data.type === 'Document';
|
data.requestId === data.loaderId && data.type === 'Document';
|
||||||
this._interceptionId = interceptionId;
|
this._interceptionId = interceptionId;
|
||||||
this.#allowInterception = allowInterception;
|
|
||||||
this.#url = data.request.url;
|
this.#url = data.request.url;
|
||||||
this.#resourceType = (data.type || 'other').toLowerCase() as ResourceType;
|
this.#resourceType = (data.type || 'other').toLowerCase() as ResourceType;
|
||||||
this.#method = data.request.method;
|
this.#method = data.request.method;
|
||||||
@ -104,10 +91,10 @@ export class CdpHTTPRequest extends HTTPRequest {
|
|||||||
this.#hasPostData = data.request.hasPostData ?? false;
|
this.#hasPostData = data.request.hasPostData ?? false;
|
||||||
this.#frame = frame;
|
this.#frame = frame;
|
||||||
this._redirectChain = redirectChain;
|
this._redirectChain = redirectChain;
|
||||||
this.#continueRequestOverrides = {};
|
|
||||||
this.#interceptHandlers = [];
|
|
||||||
this.#initiator = data.initiator;
|
this.#initiator = data.initiator;
|
||||||
|
|
||||||
|
this.interception.enabled = allowInterception;
|
||||||
|
|
||||||
for (const [key, value] of Object.entries(data.request.headers)) {
|
for (const [key, value] of Object.entries(data.request.headers)) {
|
||||||
this.#headers[key.toLowerCase()] = value;
|
this.#headers[key.toLowerCase()] = value;
|
||||||
}
|
}
|
||||||
@ -117,59 +104,6 @@ export class CdpHTTPRequest extends HTTPRequest {
|
|||||||
return this.#url;
|
return this.#url;
|
||||||
}
|
}
|
||||||
|
|
||||||
override continueRequestOverrides(): ContinueRequestOverrides {
|
|
||||||
assert(this.#allowInterception, 'Request Interception is not enabled!');
|
|
||||||
return this.#continueRequestOverrides;
|
|
||||||
}
|
|
||||||
|
|
||||||
override responseForRequest(): Partial<ResponseForRequest> | null {
|
|
||||||
assert(this.#allowInterception, 'Request Interception is not enabled!');
|
|
||||||
return this.#responseForRequest;
|
|
||||||
}
|
|
||||||
|
|
||||||
override abortErrorReason(): Protocol.Network.ErrorReason | null {
|
|
||||||
assert(this.#allowInterception, 'Request Interception is not enabled!');
|
|
||||||
return this.#abortErrorReason;
|
|
||||||
}
|
|
||||||
|
|
||||||
override interceptResolutionState(): InterceptResolutionState {
|
|
||||||
if (!this.#allowInterception) {
|
|
||||||
return {action: InterceptResolutionAction.Disabled};
|
|
||||||
}
|
|
||||||
if (this.#interceptionHandled) {
|
|
||||||
return {action: InterceptResolutionAction.AlreadyHandled};
|
|
||||||
}
|
|
||||||
return {...this.#interceptResolutionState};
|
|
||||||
}
|
|
||||||
|
|
||||||
override isInterceptResolutionHandled(): boolean {
|
|
||||||
return this.#interceptionHandled;
|
|
||||||
}
|
|
||||||
|
|
||||||
enqueueInterceptAction(
|
|
||||||
pendingHandler: () => void | PromiseLike<unknown>
|
|
||||||
): void {
|
|
||||||
this.#interceptHandlers.push(pendingHandler);
|
|
||||||
}
|
|
||||||
|
|
||||||
override async finalizeInterceptions(): Promise<void> {
|
|
||||||
await this.#interceptHandlers.reduce((promiseChain, interceptAction) => {
|
|
||||||
return promiseChain.then(interceptAction);
|
|
||||||
}, Promise.resolve());
|
|
||||||
const {action} = this.interceptResolutionState();
|
|
||||||
switch (action) {
|
|
||||||
case 'abort':
|
|
||||||
return await this.#abort(this.#abortErrorReason);
|
|
||||||
case 'respond':
|
|
||||||
if (this.#responseForRequest === null) {
|
|
||||||
throw new Error('Response is missing for the interception');
|
|
||||||
}
|
|
||||||
return await this.#respond(this.#responseForRequest);
|
|
||||||
case 'continue':
|
|
||||||
return await this.#continue(this.#continueRequestOverrides);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override resourceType(): ResourceType {
|
override resourceType(): ResourceType {
|
||||||
return this.#resourceType;
|
return this.#resourceType;
|
||||||
}
|
}
|
||||||
@ -231,46 +165,12 @@ export class CdpHTTPRequest extends HTTPRequest {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
override async continue(
|
/**
|
||||||
overrides: ContinueRequestOverrides = {},
|
* @internal
|
||||||
priority?: number
|
*/
|
||||||
): Promise<void> {
|
async _continue(overrides: ContinueRequestOverrides = {}): Promise<void> {
|
||||||
// Request interception is not supported for data: urls.
|
|
||||||
if (this.#url.startsWith('data:')) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
assert(this.#allowInterception, 'Request Interception is not enabled!');
|
|
||||||
assert(!this.#interceptionHandled, 'Request is already handled!');
|
|
||||||
if (priority === undefined) {
|
|
||||||
return await this.#continue(overrides);
|
|
||||||
}
|
|
||||||
this.#continueRequestOverrides = overrides;
|
|
||||||
if (
|
|
||||||
this.#interceptResolutionState.priority === undefined ||
|
|
||||||
priority > this.#interceptResolutionState.priority
|
|
||||||
) {
|
|
||||||
this.#interceptResolutionState = {
|
|
||||||
action: InterceptResolutionAction.Continue,
|
|
||||||
priority,
|
|
||||||
};
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (priority === this.#interceptResolutionState.priority) {
|
|
||||||
if (
|
|
||||||
this.#interceptResolutionState.action === 'abort' ||
|
|
||||||
this.#interceptResolutionState.action === 'respond'
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.#interceptResolutionState.action =
|
|
||||||
InterceptResolutionAction.Continue;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
async #continue(overrides: ContinueRequestOverrides = {}): Promise<void> {
|
|
||||||
const {url, method, postData, headers} = overrides;
|
const {url, method, postData, headers} = overrides;
|
||||||
this.#interceptionHandled = true;
|
this.interception.handled = true;
|
||||||
|
|
||||||
const postDataBinaryBase64 = postData
|
const postDataBinaryBase64 = postData
|
||||||
? Buffer.from(postData).toString('base64')
|
? Buffer.from(postData).toString('base64')
|
||||||
@ -290,45 +190,13 @@ export class CdpHTTPRequest extends HTTPRequest {
|
|||||||
headers: headers ? headersArray(headers) : undefined,
|
headers: headers ? headersArray(headers) : undefined,
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
this.#interceptionHandled = false;
|
this.interception.handled = false;
|
||||||
return handleError(error);
|
return handleError(error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
override async respond(
|
async _respond(response: Partial<ResponseForRequest>): Promise<void> {
|
||||||
response: Partial<ResponseForRequest>,
|
this.interception.handled = true;
|
||||||
priority?: number
|
|
||||||
): Promise<void> {
|
|
||||||
// Mocking responses for dataURL requests is not currently supported.
|
|
||||||
if (this.#url.startsWith('data:')) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
assert(this.#allowInterception, 'Request Interception is not enabled!');
|
|
||||||
assert(!this.#interceptionHandled, 'Request is already handled!');
|
|
||||||
if (priority === undefined) {
|
|
||||||
return await this.#respond(response);
|
|
||||||
}
|
|
||||||
this.#responseForRequest = response;
|
|
||||||
if (
|
|
||||||
this.#interceptResolutionState.priority === undefined ||
|
|
||||||
priority > this.#interceptResolutionState.priority
|
|
||||||
) {
|
|
||||||
this.#interceptResolutionState = {
|
|
||||||
action: InterceptResolutionAction.Respond,
|
|
||||||
priority,
|
|
||||||
};
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (priority === this.#interceptResolutionState.priority) {
|
|
||||||
if (this.#interceptResolutionState.action === 'abort') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.#interceptResolutionState.action = InterceptResolutionAction.Respond;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async #respond(response: Partial<ResponseForRequest>): Promise<void> {
|
|
||||||
this.#interceptionHandled = true;
|
|
||||||
|
|
||||||
const responseBody: Buffer | null =
|
const responseBody: Buffer | null =
|
||||||
response.body && isString(response.body)
|
response.body && isString(response.body)
|
||||||
@ -371,43 +239,15 @@ export class CdpHTTPRequest extends HTTPRequest {
|
|||||||
body: responseBody ? responseBody.toString('base64') : undefined,
|
body: responseBody ? responseBody.toString('base64') : undefined,
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
this.#interceptionHandled = false;
|
this.interception.handled = false;
|
||||||
return handleError(error);
|
return handleError(error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
override async abort(
|
async _abort(
|
||||||
errorCode: ErrorCode = 'failed',
|
|
||||||
priority?: number
|
|
||||||
): Promise<void> {
|
|
||||||
// Request interception is not supported for data: urls.
|
|
||||||
if (this.#url.startsWith('data:')) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const errorReason = errorReasons[errorCode];
|
|
||||||
assert(errorReason, 'Unknown error code: ' + errorCode);
|
|
||||||
assert(this.#allowInterception, 'Request Interception is not enabled!');
|
|
||||||
assert(!this.#interceptionHandled, 'Request is already handled!');
|
|
||||||
if (priority === undefined) {
|
|
||||||
return await this.#abort(errorReason);
|
|
||||||
}
|
|
||||||
this.#abortErrorReason = errorReason;
|
|
||||||
if (
|
|
||||||
this.#interceptResolutionState.priority === undefined ||
|
|
||||||
priority >= this.#interceptResolutionState.priority
|
|
||||||
) {
|
|
||||||
this.#interceptResolutionState = {
|
|
||||||
action: InterceptResolutionAction.Abort,
|
|
||||||
priority,
|
|
||||||
};
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async #abort(
|
|
||||||
errorReason: Protocol.Network.ErrorReason | null
|
errorReason: Protocol.Network.ErrorReason | null
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
this.#interceptionHandled = true;
|
this.interception.handled = true;
|
||||||
if (this._interceptionId === undefined) {
|
if (this._interceptionId === undefined) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'HTTPRequest is missing _interceptionId needed for Fetch.failRequest'
|
'HTTPRequest is missing _interceptionId needed for Fetch.failRequest'
|
||||||
@ -421,20 +261,3 @@ export class CdpHTTPRequest extends HTTPRequest {
|
|||||||
.catch(handleError);
|
.catch(handleError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const errorReasons: Record<ErrorCode, Protocol.Network.ErrorReason> = {
|
|
||||||
aborted: 'Aborted',
|
|
||||||
accessdenied: 'AccessDenied',
|
|
||||||
addressunreachable: 'AddressUnreachable',
|
|
||||||
blockedbyclient: 'BlockedByClient',
|
|
||||||
blockedbyresponse: 'BlockedByResponse',
|
|
||||||
connectionaborted: 'ConnectionAborted',
|
|
||||||
connectionclosed: 'ConnectionClosed',
|
|
||||||
connectionfailed: 'ConnectionFailed',
|
|
||||||
connectionrefused: 'ConnectionRefused',
|
|
||||||
connectionreset: 'ConnectionReset',
|
|
||||||
internetdisconnected: 'InternetDisconnected',
|
|
||||||
namenotresolved: 'NameNotResolved',
|
|
||||||
timedout: 'TimedOut',
|
|
||||||
failed: 'Failed',
|
|
||||||
} as const;
|
|
||||||
|
@ -174,13 +174,6 @@
|
|||||||
"expectations": ["SKIP"],
|
"expectations": ["SKIP"],
|
||||||
"comment": "Chrome-specific test"
|
"comment": "Chrome-specific test"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"testIdPattern": "[requestinterception-experimental.spec] *",
|
|
||||||
"platforms": ["darwin", "linux", "win32"],
|
|
||||||
"parameters": ["webDriverBiDi"],
|
|
||||||
"expectations": ["SKIP"],
|
|
||||||
"comment": "TODO: add a comment explaining why this expectation is required (include links to issues)"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"testIdPattern": "[screencast.spec] *",
|
"testIdPattern": "[screencast.spec] *",
|
||||||
"platforms": ["darwin", "linux", "win32"],
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
@ -812,12 +805,6 @@
|
|||||||
"expectations": ["SKIP"],
|
"expectations": ["SKIP"],
|
||||||
"comment": "TODO: add a comment explaining why this expectation is required (include links to issues)"
|
"comment": "TODO: add a comment explaining why this expectation is required (include links to issues)"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"testIdPattern": "[requestinterception-experimental.spec] *",
|
|
||||||
"platforms": ["darwin", "linux", "win32"],
|
|
||||||
"parameters": ["firefox", "webDriverBiDi"],
|
|
||||||
"expectations": ["PASS"]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"testIdPattern": "[requestinterception-experimental.spec] *",
|
"testIdPattern": "[requestinterception-experimental.spec] *",
|
||||||
"platforms": ["darwin", "linux", "win32"],
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
@ -825,6 +812,13 @@
|
|||||||
"expectations": ["FAIL", "SKIP"],
|
"expectations": ["FAIL", "SKIP"],
|
||||||
"comment": "TODO: add a comment explaining why this expectation is required (include links to issues)"
|
"comment": "TODO: add a comment explaining why this expectation is required (include links to issues)"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"testIdPattern": "[requestinterception-experimental.spec] cooperative request interception Page.setRequestInterception should navigate to URL with hash and fire requests without hash",
|
||||||
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
|
"parameters": ["webDriverBiDi"],
|
||||||
|
"expectations": ["FAIL"],
|
||||||
|
"comment": "BiDi spec expect the request to not trim the hash"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"testIdPattern": "[requestinterception-experimental.spec] cooperative request interception Request.continue *",
|
"testIdPattern": "[requestinterception-experimental.spec] cooperative request interception Request.continue *",
|
||||||
"platforms": ["darwin", "linux", "win32"],
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
@ -839,6 +833,13 @@
|
|||||||
"expectations": ["SKIP"],
|
"expectations": ["SKIP"],
|
||||||
"comment": "TODO: Needs full support for continueResponse in Firefox https://bugzilla.mozilla.org/show_bug.cgi?id=1853887"
|
"comment": "TODO: Needs full support for continueResponse in Firefox https://bugzilla.mozilla.org/show_bug.cgi?id=1853887"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"testIdPattern": "[requestinterception-experimental.spec] cooperative request interception Request.respond should redirect",
|
||||||
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
|
"parameters": ["webDriverBiDi"],
|
||||||
|
"expectations": ["FAIL"],
|
||||||
|
"comment": "Puppeteer request.redirectChain issue"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"testIdPattern": "[requestinterception.spec] *",
|
"testIdPattern": "[requestinterception.spec] *",
|
||||||
"platforms": ["darwin", "linux", "win32"],
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
@ -3403,13 +3404,6 @@
|
|||||||
"expectations": ["FAIL"],
|
"expectations": ["FAIL"],
|
||||||
"comment": "TODO: add a comment explaining why this expectation is required (include links to issues)"
|
"comment": "TODO: add a comment explaining why this expectation is required (include links to issues)"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"testIdPattern": "[requestinterception-experimental.spec] cooperative request interception Page.setRequestInterception should be able to access the error reason",
|
|
||||||
"platforms": ["darwin", "linux", "win32"],
|
|
||||||
"parameters": ["firefox", "webDriverBiDi"],
|
|
||||||
"expectations": ["SKIP"],
|
|
||||||
"comment": "TODO: Needs Puppeteer support for BidiHTTPRequest.abortErrorReason"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"testIdPattern": "[requestinterception-experimental.spec] cooperative request interception Page.setRequestInterception should be able to fetch dataURL and fire dataURL requests",
|
"testIdPattern": "[requestinterception-experimental.spec] cooperative request interception Page.setRequestInterception should be able to fetch dataURL and fire dataURL requests",
|
||||||
"platforms": ["darwin", "linux", "win32"],
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
@ -3439,11 +3433,11 @@
|
|||||||
"comment": "TODO: Needs support for enabling cache in BiDi without CDP https://github.com/w3c/webdriver-bidi/issues/582"
|
"comment": "TODO: Needs support for enabling cache in BiDi without CDP https://github.com/w3c/webdriver-bidi/issues/582"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"testIdPattern": "[requestinterception-experimental.spec] cooperative request interception Page.setRequestInterception should cooperatively abort by priority",
|
"testIdPattern": "[requestinterception-experimental.spec] cooperative request interception Page.setRequestInterception should cache if cache enabled",
|
||||||
"platforms": ["darwin", "linux", "win32"],
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
"parameters": ["firefox", "webDriverBiDi"],
|
"parameters": ["chrome", "webDriverBiDi"],
|
||||||
"expectations": ["SKIP"],
|
"expectations": ["FAIL"],
|
||||||
"comment": "TODO: Needs full support for continueRequest in Firefox https://bugzilla.mozilla.org/show_bug.cgi?id=1850680"
|
"comment": "TODO: Fixed in the next chromium-bidi release"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"testIdPattern": "[requestinterception-experimental.spec] cooperative request interception Page.setRequestInterception should cooperatively continue by priority",
|
"testIdPattern": "[requestinterception-experimental.spec] cooperative request interception Page.setRequestInterception should cooperatively continue by priority",
|
||||||
@ -3480,13 +3474,6 @@
|
|||||||
"expectations": ["SKIP"],
|
"expectations": ["SKIP"],
|
||||||
"comment": "TODO: Needs support for data URIs in Firefox https://bugzilla.mozilla.org/show_bug.cgi?id=1805176"
|
"comment": "TODO: Needs support for data URIs in Firefox https://bugzilla.mozilla.org/show_bug.cgi?id=1805176"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"testIdPattern": "[requestinterception-experimental.spec] cooperative request interception Page.setRequestInterception should navigate to URL with hash and fire requests without hash",
|
|
||||||
"platforms": ["darwin", "linux", "win32"],
|
|
||||||
"parameters": ["firefox", "webDriverBiDi"],
|
|
||||||
"expectations": ["FAIL"],
|
|
||||||
"comment": "TODO: Needs investigation, not clear why the test expects the hash to be removed"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"testIdPattern": "[requestinterception-experimental.spec] cooperative request interception Page.setRequestInterception should not cache if cache disabled",
|
"testIdPattern": "[requestinterception-experimental.spec] cooperative request interception Page.setRequestInterception should not cache if cache disabled",
|
||||||
"platforms": ["darwin", "linux", "win32"],
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
@ -3570,6 +3557,13 @@
|
|||||||
"parameters": ["firefox", "webDriverBiDi"],
|
"parameters": ["firefox", "webDriverBiDi"],
|
||||||
"expectations": ["PASS"]
|
"expectations": ["PASS"]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"testIdPattern": "[requestinterception-experimental.spec] cooperative request interception Request.respond should redirect",
|
||||||
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
|
"parameters": ["firefox", "webDriverBiDi"],
|
||||||
|
"expectations": ["SKIP"],
|
||||||
|
"comment": "Firefox does not support headers in provideResponse"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"testIdPattern": "[requestinterception-experimental.spec] request interception \"after each\" hook in \"request interception\"",
|
"testIdPattern": "[requestinterception-experimental.spec] request interception \"after each\" hook in \"request interception\"",
|
||||||
"platforms": ["win32"],
|
"platforms": ["win32"],
|
||||||
@ -4163,6 +4157,55 @@
|
|||||||
"expectations": ["SKIP"],
|
"expectations": ["SKIP"],
|
||||||
"comment": "TODO: add a comment explaining why this expectation is required (include links to issues)"
|
"comment": "TODO: add a comment explaining why this expectation is required (include links to issues)"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"testIdPattern": "[requestinterception-experimental.spec] cooperative request interception Page.setRequestInterception should be abortable with custom error codes",
|
||||||
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
|
"parameters": ["chrome", "headless", "webDriverBiDi"],
|
||||||
|
"expectations": ["FAIL"],
|
||||||
|
"comment": "`HTTPRequest.resourceType()` has no eqivalent in BiDi spec"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"testIdPattern": "[requestinterception-experimental.spec] cooperative request interception Page.setRequestInterception should intercept",
|
||||||
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
|
"parameters": ["chrome", "headless", "webDriverBiDi"],
|
||||||
|
"expectations": ["FAIL"],
|
||||||
|
"comment": "`request.postData()` has no eqivalent in BiDi spec"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"testIdPattern": "[requestinterception-experimental.spec] cooperative request interception Page.setRequestInterception should send referer",
|
||||||
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
|
"parameters": ["chrome", "headless", "webDriverBiDi"],
|
||||||
|
"expectations": ["FAIL"],
|
||||||
|
"comment": "`setExtraHTTPHeaders` not implemented"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"testIdPattern": "[requestinterception-experimental.spec] cooperative request interception Page.setRequestInterception should show custom HTTP headers",
|
||||||
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
|
"parameters": ["chrome", "headless", "webDriverBiDi"],
|
||||||
|
"expectations": ["FAIL"],
|
||||||
|
"comment": "`setExtraHTTPHeaders` not implemented"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"testIdPattern": "[requestinterception-experimental.spec] cooperative request interception Page.setRequestInterception should work with custom referer headers",
|
||||||
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
|
"parameters": ["chrome", "headless", "webDriverBiDi"],
|
||||||
|
"expectations": ["FAIL"],
|
||||||
|
"comment": "`setExtraHTTPHeaders` not implemented"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"testIdPattern": "[requestinterception-experimental.spec] cooperative request interception Page.setRequestInterception should work with redirects",
|
||||||
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
|
"parameters": ["chrome", "headless", "webDriverBiDi"],
|
||||||
|
"expectations": ["FAIL"],
|
||||||
|
"comment": "`HTTPRequest.resourceType()` has no eqivalent in BiDi spec"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"testIdPattern": "[requestinterception-experimental.spec] cooperative request interception Page.setRequestInterception should work with redirects for subresources",
|
||||||
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
|
"parameters": ["chrome", "headless", "webDriverBiDi"],
|
||||||
|
"expectations": ["FAIL"],
|
||||||
|
"comment": "`HTTPRequest.resourceType()` has no eqivalent in BiDi spec"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"testIdPattern": "[requestinterception.spec] request interception Page.setRequestInterception should be abortable",
|
"testIdPattern": "[requestinterception.spec] request interception Page.setRequestInterception should be abortable",
|
||||||
"platforms": ["darwin", "linux", "win32"],
|
"platforms": ["darwin", "linux", "win32"],
|
||||||
|
@ -23,8 +23,7 @@ describe('cooperative request interception', function () {
|
|||||||
|
|
||||||
describe('Page.setRequestInterception', function () {
|
describe('Page.setRequestInterception', function () {
|
||||||
const expectedActions: ActionResult[] = ['abort', 'continue', 'respond'];
|
const expectedActions: ActionResult[] = ['abort', 'continue', 'respond'];
|
||||||
while (expectedActions.length > 0) {
|
for (const expectedAction of expectedActions) {
|
||||||
const expectedAction = expectedActions.pop();
|
|
||||||
it(`should cooperatively ${expectedAction} by priority`, async () => {
|
it(`should cooperatively ${expectedAction} by priority`, async () => {
|
||||||
const {page, server} = await getTestState();
|
const {page, server} = await getTestState();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user