From ba37a4f82d8e8fc23cb13b24a73d5d7ebb8ea7b9 Mon Sep 17 00:00:00 2001 From: Andrey Lushnikov Date: Thu, 27 Jul 2017 23:11:24 -0700 Subject: [PATCH] Get rid of Body class The Body class was inlined in the Request and Response classes. This patch: - removes the Body class - adds Request.postData public property - adds Response.buffer(), Response.text() and Response.json() methods Fixes #106. --- docs/api.md | 34 ++++++++++---------- lib/NetworkManager.js | 73 ++++++++++++++++++------------------------- test/test.js | 39 ++++++++++------------- 3 files changed, 66 insertions(+), 80 deletions(-) diff --git a/docs/api.md b/docs/api.md index 357d92f7..55bb9e49 100644 --- a/docs/api.md +++ b/docs/api.md @@ -97,14 +97,18 @@ * [class: Request](#class-request) + [request.headers](#requestheaders) + [request.method](#requestmethod) + + [request.postData](#requestpostdata) + [request.response()](#requestresponse) + [request.url](#requesturl) * [class: Response](#class-response) + + [response.buffer()](#responsebuffer) + [response.headers](#responseheaders) + + [response.json()](#responsejson) + [response.ok](#responseok) + [response.request()](#responserequest) + [response.status](#responsestatus) + [response.statusText](#responsestatustext) + + [response.text()](#responsetext) + [response.url](#responseurl) * [class: InterceptedRequest](#class-interceptedrequest) + [interceptedRequest.abort()](#interceptedrequestabort) @@ -113,10 +117,6 @@ + [interceptedRequest.method](#interceptedrequestmethod) + [interceptedRequest.postData](#interceptedrequestpostdata) + [interceptedRequest.url](#interceptedrequesturl) - * [class: Body](#class-body) - + [body.buffer()](#bodybuffer) - + [body.json()](#bodyjson) - + [body.text()](#bodytext) @@ -988,6 +988,10 @@ If request gets a 'redirect' response, the request is successfully finished with Contains the request's method (GET, POST, etc.) +#### request.postData +- <[string]> + +Contains the request's post body, if any. #### request.response() - returns: <[Response]> A matching [Response] object, or `null` if the response has not been received yet. @@ -1001,9 +1005,17 @@ Contains the URL of the request. [Response] class represents responses which are received by page. [Response] implements [Body] mixin, which allows clients to call `response.json()` or `response.text()` to get different representations of response body. +#### response.buffer() +- returns: > Promise which resolves to a buffer with response body. + #### response.headers - <[Map]> A map of HTTP headers associated with the response. +#### response.json() +- returns: > Promise which resolves to a JSON representation of response body. + +This method will throw if the response body is not parsable via `JSON.parse`. + #### response.ok - <[boolean]> @@ -1012,18 +1024,18 @@ Contains a boolean stating whether the response was successful (status in the ra #### response.request() - returns: <[Request]> A matching [Request] object. - #### response.status - <[number]> Contains the status code of the response (e.g., 200 for a success). - #### response.statusText - <[string]> Contains the status message corresponding to the status code (e.g., OK for 200). +#### response.text() +- returns: > Promise which resolves to a text representation of response body. #### response.url - <[string]> @@ -1067,16 +1079,6 @@ Contains `POST` data for `POST` requests. If changed, the request url will be modified in a way that's not observable by page. Must not be changed in response to an authChallenge. -### class: Body - -#### body.buffer() -- returns: > - -#### body.json() -- returns: > - -#### body.text() -- returns: > [Array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array "Array" [boolean]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Boolean_type "Boolean" diff --git a/lib/NetworkManager.js b/lib/NetworkManager.js index 4b704fca..e82f2596 100644 --- a/lib/NetworkManager.js +++ b/lib/NetworkManager.js @@ -137,14 +137,42 @@ class NetworkManager extends EventEmitter { } } -class Body { +class Request { /** + * @param {!Object} payload + */ + constructor(payload) { + this._response = null; + this.url = payload.url; + this.method = payload.method; + this.postData = payload.postData; + this.headers = new Map(Object.entries(payload.headers)); + } + + /** + * @return {?Response} + */ + response() { + return this._response; + } +} +helper.tracePublicAPI(Request); + +class Response { + /** + * @param {?Request} request + * @param {!Object} payload * @param {function():!Promise} contentCallback */ - constructor(contentCallback) { + constructor(request, payload, contentCallback) { + this._request = request; this._contentCallback = contentCallback; - /** @type {?Promise} */ this._contentPromise = null; + this.headers = new Map(Object.entries(payload.headers)); + this.ok = payload.status >= 200 && payload.status <= 299; + this.status = payload.status; + this.statusText = payload.statusText; + this.url = payload.url; } /** @@ -171,45 +199,6 @@ class Body { let content = await this.text(); return JSON.parse(content); } -} -helper.tracePublicAPI(Body); - -class Request extends Body { - /** - * @param {!Object} payload - */ - constructor(payload) { - super(() => Promise.resolve(payload.postData || '')); - this._response = null; - this.url = payload.url; - this.method = payload.method; - this.headers = new Map(Object.entries(payload.headers)); - } - - /** - * @return {?Response} - */ - response() { - return this._response; - } -} -helper.tracePublicAPI(Request); - -class Response extends Body { - /** - * @param {?Request} request - * @param {!Object} payload - * @param {function():!Promise} contentCallback - */ - constructor(request, payload, contentCallback) { - super(contentCallback); - this._request = request; - this.headers = new Map(Object.entries(payload.headers)); - this.ok = payload.status >= 200 && payload.status <= 299; - this.status = payload.status; - this.statusText = payload.statusText; - this.url = payload.url; - } /** * @return {?Response} diff --git a/test/test.js b/test/test.js index a3563bcd..b78bc7bd 100644 --- a/test/test.js +++ b/test/test.js @@ -1133,28 +1133,6 @@ describe('Puppeteer', function() { expect(result).toBe('
hello
'); })); }); - describe('Request implements Body', function() { - it('should work', SX(async function() { - await page.navigate(EMPTY_PAGE); - server.setRoute('/post', (req, res) => res.end()); - let request = null; - page.on('request', r => request = r); - await page.evaluate(() => fetch('./post', { method: 'POST', body: JSON.stringify({foo: 'bar'})})); - expect(request).toBeTruthy(); - expect(await request.text()).toBe('{"foo":"bar"}'); - expect(await request.json()).toEqual({foo: 'bar'}); - })); - }); - describe('Response implements Body', function() { - it('should work', SX(async function() { - let response = null; - page.on('response', r => response = r); - await page.navigate(PREFIX + '/simple.json'); - expect(response).toBeTruthy(); - expect(await response.text()).toBe('{"foo": "bar"}\n'); - expect(await response.json()).toEqual({foo: 'bar'}); - })); - }); describe('Network Events', function() { it('Page.Events.Request', SX(async function() { let requests = []; @@ -1165,6 +1143,15 @@ describe('Puppeteer', function() { expect(requests[0].method).toBe('GET'); expect(requests[0].response()).toBeTruthy(); })); + it('Page.Events.Request should report post data', SX(async function() { + await page.navigate(EMPTY_PAGE); + server.setRoute('/post', (req, res) => res.end()); + let request = null; + page.on('request', r => request = r); + await page.evaluate(() => fetch('./post', { method: 'POST', body: JSON.stringify({foo: 'bar'})})); + expect(request).toBeTruthy(); + expect(request.postData).toBe('{"foo":"bar"}'); + })); it('Page.Events.Response', SX(async function() { let responses = []; page.on('response', response => responses.push(response)); @@ -1175,6 +1162,14 @@ describe('Puppeteer', function() { expect(responses[0].ok).toBe(true); expect(responses[0].request()).toBeTruthy(); })); + it('Page.Events.Response should provide body', SX(async function() { + let response = null; + page.on('response', r => response = r); + await page.navigate(PREFIX + '/simple.json'); + expect(response).toBeTruthy(); + expect(await response.text()).toBe('{"foo": "bar"}\n'); + expect(await response.json()).toEqual({foo: 'bar'}); + })); it('Page.Events.RequestFailed', SX(async function() { page.setRequestInterceptor(request => { if (request.url.endsWith('css'))