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.
This commit is contained in:
Andrey Lushnikov 2017-07-27 23:11:24 -07:00
parent 8d7d15fdb1
commit ba37a4f82d
3 changed files with 66 additions and 80 deletions

View File

@ -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)
<!-- tocstop -->
@ -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<[Buffer]>> 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<[Object]>> 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<[text]>> 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: <Promise<[Buffer]>>
#### body.json()
- returns: <Promise<[Object]>>
#### body.text()
- returns: <Promise<[text]>>
[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"

View File

@ -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<!Buffer>} contentCallback
*/
constructor(contentCallback) {
constructor(request, payload, contentCallback) {
this._request = request;
this._contentCallback = contentCallback;
/** @type {?Promise<!Buffer>} */
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<!Buffer>} 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}

View File

@ -1133,28 +1133,6 @@ describe('Puppeteer', function() {
expect(result).toBe('<div>hello</div>');
}));
});
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'))