fix(route): allow allHeaders call within route (#9300)
This commit is contained in:
parent
59532d05ea
commit
6e803f7186
|
|
@ -142,13 +142,8 @@ export class Request extends ChannelOwner<channels.RequestChannel, channels.Requ
|
||||||
|
|
||||||
_actualHeaders(): Promise<RawHeaders> {
|
_actualHeaders(): Promise<RawHeaders> {
|
||||||
if (!this._actualHeadersPromise) {
|
if (!this._actualHeadersPromise) {
|
||||||
this._actualHeadersPromise = this.response().then(response => {
|
this._actualHeadersPromise = this._wrapApiCall(async (channel: channels.RequestChannel) => {
|
||||||
// there is no response, so should we return the headers we have now?
|
return new RawHeaders((await channel.rawRequestHeaders()).headers);
|
||||||
if (!response)
|
|
||||||
return this._provisionalHeaders;
|
|
||||||
return response._wrapApiCall(async (channel: channels.ResponseChannel) => {
|
|
||||||
return new RawHeaders((await channel.rawRequestHeaders()).headers);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return this._actualHeadersPromise;
|
return this._actualHeadersPromise;
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,10 @@ export class RequestDispatcher extends Dispatcher<Request, channels.RequestIniti
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async rawRequestHeaders(params?: channels.RequestRawRequestHeadersParams): Promise<channels.RequestRawRequestHeadersResult> {
|
||||||
|
return { headers: await this._object.rawRequestHeaders() };
|
||||||
|
}
|
||||||
|
|
||||||
async response(): Promise<channels.RequestResponseResult> {
|
async response(): Promise<channels.RequestResponseResult> {
|
||||||
return { response: lookupNullableDispatcher<ResponseDispatcher>(await this._object.response()) };
|
return { response: lookupNullableDispatcher<ResponseDispatcher>(await this._object.response()) };
|
||||||
}
|
}
|
||||||
|
|
@ -86,10 +90,6 @@ export class ResponseDispatcher extends Dispatcher<Response, channels.ResponseIn
|
||||||
return { value: await this._object.serverAddr() || undefined };
|
return { value: await this._object.serverAddr() || undefined };
|
||||||
}
|
}
|
||||||
|
|
||||||
async rawRequestHeaders(params?: channels.ResponseRawRequestHeadersParams): Promise<channels.ResponseRawRequestHeadersResult> {
|
|
||||||
return { headers: await this._object.rawRequestHeaders() };
|
|
||||||
}
|
|
||||||
|
|
||||||
async rawResponseHeaders(params?: channels.ResponseRawResponseHeadersParams): Promise<channels.ResponseRawResponseHeadersResult> {
|
async rawResponseHeaders(params?: channels.ResponseRawResponseHeadersParams): Promise<channels.ResponseRawResponseHeadersResult> {
|
||||||
return { headers: await this._object.rawResponseHeaders() };
|
return { headers: await this._object.rawResponseHeaders() };
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2770,12 +2770,18 @@ export type RequestInitializer = {
|
||||||
};
|
};
|
||||||
export interface RequestChannel extends Channel {
|
export interface RequestChannel extends Channel {
|
||||||
response(params?: RequestResponseParams, metadata?: Metadata): Promise<RequestResponseResult>;
|
response(params?: RequestResponseParams, metadata?: Metadata): Promise<RequestResponseResult>;
|
||||||
|
rawRequestHeaders(params?: RequestRawRequestHeadersParams, metadata?: Metadata): Promise<RequestRawRequestHeadersResult>;
|
||||||
}
|
}
|
||||||
export type RequestResponseParams = {};
|
export type RequestResponseParams = {};
|
||||||
export type RequestResponseOptions = {};
|
export type RequestResponseOptions = {};
|
||||||
export type RequestResponseResult = {
|
export type RequestResponseResult = {
|
||||||
response?: ResponseChannel,
|
response?: ResponseChannel,
|
||||||
};
|
};
|
||||||
|
export type RequestRawRequestHeadersParams = {};
|
||||||
|
export type RequestRawRequestHeadersOptions = {};
|
||||||
|
export type RequestRawRequestHeadersResult = {
|
||||||
|
headers: NameValue[],
|
||||||
|
};
|
||||||
|
|
||||||
export interface RequestEvents {
|
export interface RequestEvents {
|
||||||
}
|
}
|
||||||
|
|
@ -2864,7 +2870,6 @@ export interface ResponseChannel extends Channel {
|
||||||
body(params?: ResponseBodyParams, metadata?: Metadata): Promise<ResponseBodyResult>;
|
body(params?: ResponseBodyParams, metadata?: Metadata): Promise<ResponseBodyResult>;
|
||||||
securityDetails(params?: ResponseSecurityDetailsParams, metadata?: Metadata): Promise<ResponseSecurityDetailsResult>;
|
securityDetails(params?: ResponseSecurityDetailsParams, metadata?: Metadata): Promise<ResponseSecurityDetailsResult>;
|
||||||
serverAddr(params?: ResponseServerAddrParams, metadata?: Metadata): Promise<ResponseServerAddrResult>;
|
serverAddr(params?: ResponseServerAddrParams, metadata?: Metadata): Promise<ResponseServerAddrResult>;
|
||||||
rawRequestHeaders(params?: ResponseRawRequestHeadersParams, metadata?: Metadata): Promise<ResponseRawRequestHeadersResult>;
|
|
||||||
rawResponseHeaders(params?: ResponseRawResponseHeadersParams, metadata?: Metadata): Promise<ResponseRawResponseHeadersResult>;
|
rawResponseHeaders(params?: ResponseRawResponseHeadersParams, metadata?: Metadata): Promise<ResponseRawResponseHeadersResult>;
|
||||||
sizes(params?: ResponseSizesParams, metadata?: Metadata): Promise<ResponseSizesResult>;
|
sizes(params?: ResponseSizesParams, metadata?: Metadata): Promise<ResponseSizesResult>;
|
||||||
}
|
}
|
||||||
|
|
@ -2883,11 +2888,6 @@ export type ResponseServerAddrOptions = {};
|
||||||
export type ResponseServerAddrResult = {
|
export type ResponseServerAddrResult = {
|
||||||
value?: RemoteAddr,
|
value?: RemoteAddr,
|
||||||
};
|
};
|
||||||
export type ResponseRawRequestHeadersParams = {};
|
|
||||||
export type ResponseRawRequestHeadersOptions = {};
|
|
||||||
export type ResponseRawRequestHeadersResult = {
|
|
||||||
headers: NameValue[],
|
|
||||||
};
|
|
||||||
export type ResponseRawResponseHeadersParams = {};
|
export type ResponseRawResponseHeadersParams = {};
|
||||||
export type ResponseRawResponseHeadersOptions = {};
|
export type ResponseRawResponseHeadersOptions = {};
|
||||||
export type ResponseRawResponseHeadersResult = {
|
export type ResponseRawResponseHeadersResult = {
|
||||||
|
|
|
||||||
|
|
@ -2324,6 +2324,11 @@ Request:
|
||||||
returns:
|
returns:
|
||||||
response: Response?
|
response: Response?
|
||||||
|
|
||||||
|
rawRequestHeaders:
|
||||||
|
returns:
|
||||||
|
headers:
|
||||||
|
type: array
|
||||||
|
items: NameValue
|
||||||
|
|
||||||
|
|
||||||
Route:
|
Route:
|
||||||
|
|
@ -2407,12 +2412,6 @@ Response:
|
||||||
returns:
|
returns:
|
||||||
value: RemoteAddr?
|
value: RemoteAddr?
|
||||||
|
|
||||||
rawRequestHeaders:
|
|
||||||
returns:
|
|
||||||
headers:
|
|
||||||
type: array
|
|
||||||
items: NameValue
|
|
||||||
|
|
||||||
rawResponseHeaders:
|
rawResponseHeaders:
|
||||||
returns:
|
returns:
|
||||||
headers:
|
headers:
|
||||||
|
|
|
||||||
|
|
@ -1096,6 +1096,7 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
|
||||||
state: tOptional(tEnum(['attached', 'detached', 'visible', 'hidden'])),
|
state: tOptional(tEnum(['attached', 'detached', 'visible', 'hidden'])),
|
||||||
});
|
});
|
||||||
scheme.RequestResponseParams = tOptional(tObject({}));
|
scheme.RequestResponseParams = tOptional(tObject({}));
|
||||||
|
scheme.RequestRawRequestHeadersParams = tOptional(tObject({}));
|
||||||
scheme.RouteAbortParams = tObject({
|
scheme.RouteAbortParams = tObject({
|
||||||
errorCode: tOptional(tString),
|
errorCode: tOptional(tString),
|
||||||
});
|
});
|
||||||
|
|
@ -1128,7 +1129,6 @@ export function createScheme(tChannel: (name: string) => Validator): Scheme {
|
||||||
scheme.ResponseBodyParams = tOptional(tObject({}));
|
scheme.ResponseBodyParams = tOptional(tObject({}));
|
||||||
scheme.ResponseSecurityDetailsParams = tOptional(tObject({}));
|
scheme.ResponseSecurityDetailsParams = tOptional(tObject({}));
|
||||||
scheme.ResponseServerAddrParams = tOptional(tObject({}));
|
scheme.ResponseServerAddrParams = tOptional(tObject({}));
|
||||||
scheme.ResponseRawRequestHeadersParams = tOptional(tObject({}));
|
|
||||||
scheme.ResponseRawResponseHeadersParams = tOptional(tObject({}));
|
scheme.ResponseRawResponseHeadersParams = tOptional(tObject({}));
|
||||||
scheme.ResponseSizesParams = tOptional(tObject({}));
|
scheme.ResponseSizesParams = tOptional(tObject({}));
|
||||||
scheme.SecurityDetails = tObject({
|
scheme.SecurityDetails = tObject({
|
||||||
|
|
|
||||||
|
|
@ -154,6 +154,13 @@ export class CRNetworkManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
_onRequestPaused(workerFrame: frames.Frame | undefined, event: Protocol.Fetch.requestPausedPayload) {
|
_onRequestPaused(workerFrame: frames.Frame | undefined, event: Protocol.Fetch.requestPausedPayload) {
|
||||||
|
if (!event.responseStatusCode && !event.responseErrorReason) {
|
||||||
|
// Request intercepted, deliver signal to the tracker.
|
||||||
|
const request = this._requestIdToRequest.get(event.networkId!);
|
||||||
|
if (request)
|
||||||
|
this._responseExtraInfoTracker.requestPaused(request.request, event);
|
||||||
|
}
|
||||||
|
|
||||||
if (!this._userRequestInterceptionEnabled && this._protocolRequestInterceptionEnabled) {
|
if (!this._userRequestInterceptionEnabled && this._protocolRequestInterceptionEnabled) {
|
||||||
this._client._sendMayFail('Fetch.continueRequest', {
|
this._client._sendMayFail('Fetch.continueRequest', {
|
||||||
requestId: event.requestId
|
requestId: event.requestId
|
||||||
|
|
@ -619,6 +626,13 @@ class ResponseExtraInfoTracker {
|
||||||
this._innerResponseReceived(info, event.response);
|
this._innerResponseReceived(info, event.response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
requestPaused(request: network.Request, event: Protocol.Fetch.requestPausedPayload) {
|
||||||
|
// requestWillBeSentExtraInfo is not being called when interception
|
||||||
|
// is enabled. But interception is mutually exclusive with the redirects.
|
||||||
|
// So we can use the headers from the Fetch.requestPausedPayload immediately.
|
||||||
|
request.setRawRequestHeaders(headersObjectToArray(event.request.headers, '\n'));
|
||||||
|
}
|
||||||
|
|
||||||
private _innerResponseReceived(info: RequestInfo, response: Protocol.Network.Response) {
|
private _innerResponseReceived(info: RequestInfo, response: Protocol.Network.Response) {
|
||||||
if (!response.connectionId) {
|
if (!response.connectionId) {
|
||||||
// Starting with this response we no longer can guarantee that response and extra info correspond to the same index.
|
// Starting with this response we no longer can guarantee that response and extra info correspond to the same index.
|
||||||
|
|
@ -684,7 +698,7 @@ class ResponseExtraInfoTracker {
|
||||||
const response = info.responses[index];
|
const response = info.responses[index];
|
||||||
const requestExtraInfo = info.requestWillBeSentExtraInfo[index];
|
const requestExtraInfo = info.requestWillBeSentExtraInfo[index];
|
||||||
if (response && requestExtraInfo)
|
if (response && requestExtraInfo)
|
||||||
response.setRawRequestHeaders(headersObjectToArray(requestExtraInfo.headers, '\n'));
|
response.request().setRawRequestHeaders(headersObjectToArray(requestExtraInfo.headers, '\n'));
|
||||||
const responseExtraInfo = info.responseReceivedExtraInfo[index];
|
const responseExtraInfo = info.responseReceivedExtraInfo[index];
|
||||||
if (response && responseExtraInfo) {
|
if (response && responseExtraInfo) {
|
||||||
response.setRawResponseHeaders(headersObjectToArray(responseExtraInfo.headers, '\n'));
|
response.setRawResponseHeaders(headersObjectToArray(responseExtraInfo.headers, '\n'));
|
||||||
|
|
|
||||||
|
|
@ -100,6 +100,7 @@ export class Request extends SdkObject {
|
||||||
private _postData: Buffer | null;
|
private _postData: Buffer | null;
|
||||||
readonly _headers: types.HeadersArray;
|
readonly _headers: types.HeadersArray;
|
||||||
private _headersMap = new Map<string, string>();
|
private _headersMap = new Map<string, string>();
|
||||||
|
private _rawRequestHeadersPromise: ManualPromise<types.HeadersArray> | undefined;
|
||||||
private _frame: frames.Frame;
|
private _frame: frames.Frame;
|
||||||
private _waitForResponsePromise = new ManualPromise<Response | null>();
|
private _waitForResponsePromise = new ManualPromise<Response | null>();
|
||||||
_responseEndTiming = -1;
|
_responseEndTiming = -1;
|
||||||
|
|
@ -153,8 +154,23 @@ export class Request extends SdkObject {
|
||||||
return this._headersMap.get(name);
|
return this._headersMap.get(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
async rawHeaders(): Promise<NameValue[]> {
|
setWillReceiveExtraHeaders() {
|
||||||
return this._headers;
|
if (!this._rawRequestHeadersPromise)
|
||||||
|
this._rawRequestHeadersPromise = new ManualPromise();
|
||||||
|
}
|
||||||
|
|
||||||
|
setRawRequestHeaders(headers: types.HeadersArray) {
|
||||||
|
if (!this._rawRequestHeadersPromise)
|
||||||
|
this._rawRequestHeadersPromise = new ManualPromise();
|
||||||
|
this._rawRequestHeadersPromise!.resolve(headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
async rawRequestHeaders(): Promise<NameValue[]> {
|
||||||
|
return this._rawRequestHeadersPromise || Promise.resolve(this._headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
rawRequestHeadersPromise(): Promise<types.HeadersArray> | undefined {
|
||||||
|
return this._rawRequestHeadersPromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
response(): PromiseLike<Response | null> {
|
response(): PromiseLike<Response | null> {
|
||||||
|
|
@ -197,6 +213,17 @@ export class Request extends SdkObject {
|
||||||
bodySize(): number {
|
bodySize(): number {
|
||||||
return this.postDataBuffer()?.length || 0;
|
return this.postDataBuffer()?.length || 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async requestHeadersSize(): Promise<number> {
|
||||||
|
let headersSize = 4; // 4 = 2 spaces + 2 line breaks (GET /path \r\n)
|
||||||
|
headersSize += this.method().length;
|
||||||
|
headersSize += (new URL(this.url())).pathname.length;
|
||||||
|
headersSize += 8; // httpVersion
|
||||||
|
const headers = this.rawRequestHeadersPromise() ? await this.rawRequestHeadersPromise()! : this._headers;
|
||||||
|
for (const header of headers)
|
||||||
|
headersSize += header.name.length + header.value.length + 4; // 4 = ': ' + '\r\n'
|
||||||
|
return headersSize;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Route extends SdkObject {
|
export class Route extends SdkObject {
|
||||||
|
|
@ -316,7 +343,6 @@ export class Response extends SdkObject {
|
||||||
private _timing: ResourceTiming;
|
private _timing: ResourceTiming;
|
||||||
private _serverAddrPromise = new ManualPromise<RemoteAddr | undefined>();
|
private _serverAddrPromise = new ManualPromise<RemoteAddr | undefined>();
|
||||||
private _securityDetailsPromise = new ManualPromise<SecurityDetails | undefined>();
|
private _securityDetailsPromise = new ManualPromise<SecurityDetails | undefined>();
|
||||||
private _rawRequestHeadersPromise: ManualPromise<types.HeadersArray> | undefined;
|
|
||||||
private _rawResponseHeadersPromise: ManualPromise<types.HeadersArray> | undefined;
|
private _rawResponseHeadersPromise: ManualPromise<types.HeadersArray> | undefined;
|
||||||
private _httpVersion: string | undefined;
|
private _httpVersion: string | undefined;
|
||||||
|
|
||||||
|
|
@ -372,25 +398,15 @@ export class Response extends SdkObject {
|
||||||
return this._headersMap.get(name);
|
return this._headersMap.get(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
async rawRequestHeaders(): Promise<NameValue[]> {
|
|
||||||
return this._rawRequestHeadersPromise || Promise.resolve(this._request._headers);
|
|
||||||
}
|
|
||||||
|
|
||||||
async rawResponseHeaders(): Promise<NameValue[]> {
|
async rawResponseHeaders(): Promise<NameValue[]> {
|
||||||
return this._rawResponseHeadersPromise || Promise.resolve(this._headers);
|
return this._rawResponseHeadersPromise || Promise.resolve(this._headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
setWillReceiveExtraHeaders() {
|
setWillReceiveExtraHeaders() {
|
||||||
this._rawRequestHeadersPromise = new ManualPromise();
|
this._request.setWillReceiveExtraHeaders();
|
||||||
this._rawResponseHeadersPromise = new ManualPromise();
|
this._rawResponseHeadersPromise = new ManualPromise();
|
||||||
}
|
}
|
||||||
|
|
||||||
setRawRequestHeaders(headers: types.HeadersArray) {
|
|
||||||
if (!this._rawRequestHeadersPromise)
|
|
||||||
this._rawRequestHeadersPromise = new ManualPromise();
|
|
||||||
this._rawRequestHeadersPromise!.resolve(headers);
|
|
||||||
}
|
|
||||||
|
|
||||||
setRawResponseHeaders(headers: types.HeadersArray) {
|
setRawResponseHeaders(headers: types.HeadersArray) {
|
||||||
if (!this._rawResponseHeadersPromise)
|
if (!this._rawResponseHeadersPromise)
|
||||||
this._rawResponseHeadersPromise = new ManualPromise();
|
this._rawResponseHeadersPromise = new ManualPromise();
|
||||||
|
|
@ -436,17 +452,6 @@ export class Response extends SdkObject {
|
||||||
return this._httpVersion;
|
return this._httpVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _requestHeadersSize(): Promise<number> {
|
|
||||||
let headersSize = 4; // 4 = 2 spaces + 2 line breaks (GET /path \r\n)
|
|
||||||
headersSize += this._request.method().length;
|
|
||||||
headersSize += (new URL(this.url())).pathname.length;
|
|
||||||
headersSize += 8; // httpVersion
|
|
||||||
const headers = this._rawRequestHeadersPromise ? await this._rawRequestHeadersPromise : this._request._headers;
|
|
||||||
for (const header of headers)
|
|
||||||
headersSize += header.name.length + header.value.length + 4; // 4 = ': ' + '\r\n'
|
|
||||||
return headersSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _responseHeadersSize(): Promise<number> {
|
private async _responseHeadersSize(): Promise<number> {
|
||||||
if (this._request.responseSize.responseHeadersSize)
|
if (this._request.responseSize.responseHeadersSize)
|
||||||
return this._request.responseSize.responseHeadersSize;
|
return this._request.responseSize.responseHeadersSize;
|
||||||
|
|
@ -467,7 +472,7 @@ export class Response extends SdkObject {
|
||||||
|
|
||||||
async sizes(): Promise<ResourceSizes> {
|
async sizes(): Promise<ResourceSizes> {
|
||||||
await this._finishedPromise;
|
await this._finishedPromise;
|
||||||
const requestHeadersSize = await this._requestHeadersSize();
|
const requestHeadersSize = await this._request.requestHeadersSize();
|
||||||
const responseHeadersSize = await this._responseHeadersSize();
|
const responseHeadersSize = await this._responseHeadersSize();
|
||||||
let { encodedBodySize } = this._request.responseSize;
|
let { encodedBodySize } = this._request.responseSize;
|
||||||
if (!encodedBodySize) {
|
if (!encodedBodySize) {
|
||||||
|
|
|
||||||
|
|
@ -320,7 +320,7 @@ export class HarTracer {
|
||||||
if (details)
|
if (details)
|
||||||
harEntry._securityDetails = details;
|
harEntry._securityDetails = details;
|
||||||
}));
|
}));
|
||||||
this._addBarrier(page, response.rawRequestHeaders().then(headers => {
|
this._addBarrier(page, request.rawRequestHeaders().then(headers => {
|
||||||
for (const header of headers.filter(header => header.name.toLowerCase() === 'cookie'))
|
for (const header of headers.filter(header => header.name.toLowerCase() === 'cookie'))
|
||||||
harEntry.request.cookies.push(...header.value.split(';').map(parseCookie));
|
harEntry.request.cookies.push(...header.value.split(';').map(parseCookie));
|
||||||
harEntry.request.headers = headers;
|
harEntry.request.headers = headers;
|
||||||
|
|
|
||||||
|
|
@ -1016,7 +1016,7 @@ export class WKPage implements PageDelegate {
|
||||||
const headers = { ...event.response.requestHeaders };
|
const headers = { ...event.response.requestHeaders };
|
||||||
if (!headers['host'])
|
if (!headers['host'])
|
||||||
headers['Host'] = new URL(request.request.url()).host;
|
headers['Host'] = new URL(request.request.url()).host;
|
||||||
response.setRawRequestHeaders(headersObjectToArray(headers));
|
request.request.setRawRequestHeaders(headersObjectToArray(headers));
|
||||||
}
|
}
|
||||||
this._page._frameManager.requestReceivedResponse(response);
|
this._page._frameManager.requestReceivedResponse(response);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -672,3 +672,13 @@ it('should support the times parameter with route matching', async ({ page, serv
|
||||||
await page.goto(server.EMPTY_PAGE);
|
await page.goto(server.EMPTY_PAGE);
|
||||||
expect(intercepted).toHaveLength(1);
|
expect(intercepted).toHaveLength(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should contain raw header', async ({ page, server }) => {
|
||||||
|
let headers: any;
|
||||||
|
await page.route('**/*', async route => {
|
||||||
|
headers = await route.request().allHeaders();
|
||||||
|
route.continue();
|
||||||
|
});
|
||||||
|
await page.goto(server.PREFIX + '/empty.html');
|
||||||
|
expect(headers.accept).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue