From a271145b0663ef9de1903dd0eb9fd5366465bed7 Mon Sep 17 00:00:00 2001 From: Jan Scheffler Date: Wed, 29 Sep 2021 17:14:21 +0200 Subject: [PATCH] feat: add initiator to HTTPRequest (#7614) Co-Authored-By: atersolis --- docs/api.md | 9 ++++++++ src/common/HTTPRequest.ts | 9 ++++++++ test/assets/initiator.html | 2 ++ test/assets/initiator.js | 8 ++++++++ test/network.spec.ts | 42 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 70 insertions(+) create mode 100644 test/assets/initiator.html create mode 100644 test/assets/initiator.js diff --git a/docs/api.md b/docs/api.md index a4018c43ab1b0..6159c0ab1596b 100644 --- a/docs/api.md +++ b/docs/api.md @@ -341,6 +341,7 @@ * [httpRequest.finalizeInterceptions()](#httprequestfinalizeinterceptions) * [httpRequest.frame()](#httprequestframe) * [httpRequest.headers()](#httprequestheaders) + * [httpRequest.initiator()](#httprequestinitiator) * [httpRequest.isNavigationRequest()](#httprequestisnavigationrequest) * [httpRequest.method()](#httprequestmethod) * [httpRequest.postData()](#httprequestpostdata) @@ -4792,6 +4793,14 @@ When in Cooperative Mode, awaits pending interception handlers and then decides - returns: <[Object]> An object with HTTP headers associated with the request. All header names are lower-case. +#### httpRequest.initiator() + +- returns: <[Object]> An object describing the initiator of the request + - `type` <[string]> Type of this initiator. Possible values: `parser`, `script`, `preload`, `SignedExchange` and `other`. + - `stack` JavaScript stack trace for the initiator, set for `script` only. + - `url` Initiator URL, set for `parser`, `script` and `SignedExchange` type. + - `lineNumber` 0 based initiator line number, set for `parser` and `script`. + #### httpRequest.isNavigationRequest() - returns: <[boolean]> diff --git a/src/common/HTTPRequest.ts b/src/common/HTTPRequest.ts index 22a6442e06d60..6f9cc20a644ef 100644 --- a/src/common/HTTPRequest.ts +++ b/src/common/HTTPRequest.ts @@ -130,6 +130,7 @@ export class HTTPRequest { private _currentStrategy: InterceptResolutionStrategy; private _currentPriority: number | undefined; private _interceptActions: Array<() => void | PromiseLike>; + private _initiator: Protocol.Network.Initiator; /** * @internal @@ -158,6 +159,7 @@ export class HTTPRequest { this._currentStrategy = 'none'; this._currentPriority = undefined; this._interceptActions = []; + this._initiator = event.initiator; for (const key of Object.keys(event.request.headers)) this._headers[key.toLowerCase()] = event.request.headers[key]; @@ -298,6 +300,13 @@ export class HTTPRequest { return this._isNavigationRequest; } + /** + * @returns the initiator of the request. + */ + initiator(): Protocol.Network.Initiator { + return this._initiator; + } + /** * A `redirectChain` is a chain of requests initiated to fetch a resource. * @remarks diff --git a/test/assets/initiator.html b/test/assets/initiator.html new file mode 100644 index 0000000000000..12889d324271c --- /dev/null +++ b/test/assets/initiator.html @@ -0,0 +1,2 @@ + + diff --git a/test/assets/initiator.js b/test/assets/initiator.js new file mode 100644 index 0000000000000..642e775f313b5 --- /dev/null +++ b/test/assets/initiator.js @@ -0,0 +1,8 @@ +const script = document.createElement('script'); +script.src = './injectedfile.js'; +document.body.appendChild(script); + +const style = document.createElement('link'); +style.rel = 'stylesheet'; +style.href = './injectedstyle.css'; +document.head.appendChild(style); diff --git a/test/network.spec.ts b/test/network.spec.ts index 787fee18f43ef..6775fdce199fa 100644 --- a/test/network.spec.ts +++ b/test/network.spec.ts @@ -137,6 +137,48 @@ describe('network', function () { }); }); + describeFailsFirefox('Request.initiator', () => { + it('shoud return the initiator', async () => { + const { page, server } = getTestState(); + + const initiators = new Map(); + page.on('request', (request) => + initiators.set(request.url().split('/').pop(), request.initiator()) + ); + await page.goto(server.PREFIX + '/initiator.html'); + + expect(initiators.get('initiator.html').type).toBe('other'); + expect(initiators.get('initiator.js').type).toBe('parser'); + expect(initiators.get('initiator.js').url).toBe( + server.PREFIX + '/initiator.html' + ); + expect(initiators.get('frame.html').type).toBe('parser'); + expect(initiators.get('frame.html').url).toBe( + server.PREFIX + '/initiator.html' + ); + expect(initiators.get('script.js').type).toBe('parser'); + expect(initiators.get('script.js').url).toBe( + server.PREFIX + '/frames/frame.html' + ); + expect(initiators.get('style.css').type).toBe('parser'); + expect(initiators.get('style.css').url).toBe( + server.PREFIX + '/frames/frame.html' + ); + expect(initiators.get('initiator.js').type).toBe('parser'); + expect(initiators.get('injectedfile.js').type).toBe('script'); + expect(initiators.get('injectedfile.js').stack.callFrames[0].url).toBe( + server.PREFIX + '/initiator.js' + ); + expect(initiators.get('injectedstyle.css').type).toBe('script'); + expect(initiators.get('injectedstyle.css').stack.callFrames[0].url).toBe( + server.PREFIX + '/initiator.js' + ); + expect(initiators.get('initiator.js').url).toBe( + server.PREFIX + '/initiator.html' + ); + }); + }); + describeFailsFirefox('Response.fromCache', function () { it('should return |false| for non-cached content', async () => { const { page, server } = getTestState();