fix(webdriver): request redirect chain (#12168)

This commit is contained in:
Nikolay Vitkov 2024-04-02 21:54:13 +02:00 committed by GitHub
parent 6dfb560fa5
commit d345055af3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 40 additions and 43 deletions

View File

@ -402,11 +402,9 @@ export class BidiFrame extends Frame {
if (!request) { if (!request) {
return null; return null;
} }
const httpRequest = requests.get(request)!; const lastRequest = request.lastRedirect ?? request;
const lastRedirect = httpRequest.redirectChain().at(-1); const httpRequest = requests.get(lastRequest)!;
return ( return httpRequest.response();
lastRedirect !== undefined ? lastRedirect : httpRequest
).response();
}), }),
raceWith( raceWith(
timeout(ms), timeout(ms),

View File

@ -31,20 +31,24 @@ export const requests = new WeakMap<Request, BidiHTTPRequest>();
export class BidiHTTPRequest extends HTTPRequest { export class BidiHTTPRequest extends HTTPRequest {
static from( static from(
bidiRequest: Request, bidiRequest: Request,
frame: BidiFrame | undefined frame: BidiFrame | undefined,
redirect?: BidiHTTPRequest
): BidiHTTPRequest { ): BidiHTTPRequest {
const request = new BidiHTTPRequest(bidiRequest, frame); const request = new BidiHTTPRequest(bidiRequest, frame, redirect);
request.#initialize(); request.#initialize();
return request; return request;
} }
#redirectBy: BidiHTTPRequest | undefined;
#redirect: BidiHTTPRequest | undefined;
#response: BidiHTTPResponse | null = null; #response: BidiHTTPResponse | null = null;
override readonly id: string; override readonly id: string;
readonly #frame: BidiFrame | undefined; readonly #frame: BidiFrame | undefined;
readonly #request: Request; readonly #request: Request;
private constructor(request: Request, frame: BidiFrame | undefined) { private constructor(
request: Request,
frame: BidiFrame | undefined,
redirectBy?: BidiHTTPRequest
) {
super(); super();
requests.set(request, this); requests.set(request, this);
@ -52,6 +56,7 @@ export class BidiHTTPRequest extends HTTPRequest {
this.#request = request; this.#request = request;
this.#frame = frame; this.#frame = frame;
this.#redirectBy = redirectBy;
this.id = request.id; this.id = request.id;
} }
@ -61,8 +66,8 @@ export class BidiHTTPRequest extends HTTPRequest {
#initialize() { #initialize() {
this.#request.on('redirect', request => { this.#request.on('redirect', request => {
this.#redirect = BidiHTTPRequest.from(request, this.#frame); const httpRequest = BidiHTTPRequest.from(request, this.#frame, this);
void this.#redirect.finalizeInterceptions(); void httpRequest.finalizeInterceptions();
}); });
this.#request.once('success', data => { this.#request.once('success', data => {
this.#response = BidiHTTPResponse.from(data, this); this.#response = BidiHTTPResponse.from(data, this);
@ -123,13 +128,13 @@ export class BidiHTTPRequest extends HTTPRequest {
} }
override redirectChain(): BidiHTTPRequest[] { override redirectChain(): BidiHTTPRequest[] {
if (this.#redirect === undefined) { if (this.#redirectBy === undefined) {
return []; return [];
} }
const redirects = [this.#redirect]; const redirects = [this.#redirectBy];
for (const redirect of redirects) { for (const redirect of redirects) {
if (redirect.#redirect !== undefined) { if (redirect.#redirectBy !== undefined) {
redirects.push(redirect.#redirect); redirects.push(redirect.#redirectBy);
} }
} }
return redirects; return redirects;

View File

@ -6,7 +6,6 @@
import {EventEmitter} from '../../common/EventEmitter.js'; import {EventEmitter} from '../../common/EventEmitter.js';
import {inertIfDisposed} from '../../util/decorators.js'; import {inertIfDisposed} from '../../util/decorators.js';
import {Deferred} from '../../util/Deferred.js';
import {DisposableStack, disposeSymbol} from '../../util/disposable.js'; import {DisposableStack, disposeSymbol} from '../../util/disposable.js';
import type {BrowsingContext} from './BrowsingContext.js'; import type {BrowsingContext} from './BrowsingContext.js';
@ -44,7 +43,7 @@ export class Navigation extends EventEmitter<{
#navigation: Navigation | undefined; #navigation: Navigation | undefined;
readonly #browsingContext: BrowsingContext; readonly #browsingContext: BrowsingContext;
readonly #disposables = new DisposableStack(); readonly #disposables = new DisposableStack();
readonly #id = new Deferred<string | null>(); #id?: string | null;
// keep-sorted end // keep-sorted end
private constructor(context: BrowsingContext) { private constructor(context: BrowsingContext) {
@ -69,7 +68,6 @@ export class Navigation extends EventEmitter<{
browsingContextEmitter.on('request', ({request}) => { browsingContextEmitter.on('request', ({request}) => {
if ( if (
request.navigation === undefined || request.navigation === undefined ||
this.#request !== undefined ||
// If a request with a navigation ID comes in, then the navigation ID is // If a request with a navigation ID comes in, then the navigation ID is
// for this navigation. // for this navigation.
!this.#matches(request.navigation) !this.#matches(request.navigation)
@ -79,6 +77,13 @@ export class Navigation extends EventEmitter<{
this.#request = request; this.#request = request;
this.emit('request', request); this.emit('request', request);
const requestEmitter = this.#disposables.use(
new EventEmitter(this.#request)
);
requestEmitter.on('redirect', request => {
this.#request = request;
});
}); });
const sessionEmitter = this.#disposables.use( const sessionEmitter = this.#disposables.use(
@ -139,11 +144,11 @@ export class Navigation extends EventEmitter<{
if (this.#navigation !== undefined && !this.#navigation.disposed) { if (this.#navigation !== undefined && !this.#navigation.disposed) {
return false; return false;
} }
if (!this.#id.resolved()) { if (this.#id === undefined) {
this.#id.resolve(navigation); this.#id = navigation;
return true; return true;
} }
return this.#id.value() === navigation; return this.#id === navigation;
} }
// keep-sorted start block=yes // keep-sorted start block=yes

View File

@ -135,6 +135,16 @@ export class Request extends EventEmitter<{
get redirect(): Request | undefined { get redirect(): Request | undefined {
return this.#redirect; return this.#redirect;
} }
get lastRedirect(): Request | undefined {
let redirect = this.#redirect;
while (redirect) {
if (redirect && !redirect.#redirect) {
return redirect;
}
redirect = redirect.#redirect;
}
return redirect;
}
get response(): Bidi.Network.ResponseData | undefined { get response(): Bidi.Network.ResponseData | undefined {
return this.#response; return this.#response;
} }

View File

@ -833,13 +833,6 @@
"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"],
@ -3557,13 +3550,6 @@
"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"],
@ -3745,13 +3731,6 @@
"parameters": ["firefox", "webDriverBiDi"], "parameters": ["firefox", "webDriverBiDi"],
"expectations": ["PASS"] "expectations": ["PASS"]
}, },
{
"testIdPattern": "[requestinterception.spec] request interception Request.respond should redirect",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["chrome", "webDriverBiDi"],
"expectations": ["FAIL"],
"comment": "Puppeteer request.redirectChain issue"
},
{ {
"testIdPattern": "[screenshot.spec] Screenshots Cdp should use scale for clip", "testIdPattern": "[screenshot.spec] Screenshots Cdp should use scale for clip",
"platforms": ["darwin", "linux", "win32"], "platforms": ["darwin", "linux", "win32"],