mirror of
https://github.com/puppeteer/puppeteer
synced 2024-06-14 14:02:48 +00:00
Implement Body interface for both Request and Response
This patch partially implements Fetch API's [Body](https://developer.mozilla.org/en-US/docs/Web/API/Body) interface for both Request and Response. Fixes #26.
This commit is contained in:
@@ -94,7 +94,7 @@ class NetworkManager extends EventEmitter {
|
|||||||
_onRequestWillBeSent(event) {
|
_onRequestWillBeSent(event) {
|
||||||
if (event.redirectResponse) {
|
if (event.redirectResponse) {
|
||||||
let request = this._idToRequest.get(event.requestId);
|
let request = this._idToRequest.get(event.requestId);
|
||||||
let response = new Response(request, event.redirectResponse);
|
let response = new Response(request, event.redirectResponse, this._getResponseBody.bind(this, event.requestId));
|
||||||
request._response = response;
|
request._response = response;
|
||||||
this.emit(NetworkManager.Events.Response, response);
|
this.emit(NetworkManager.Events.Response, response);
|
||||||
this.emit(NetworkManager.Events.RequestFinished, request);
|
this.emit(NetworkManager.Events.RequestFinished, request);
|
||||||
@@ -109,7 +109,7 @@ class NetworkManager extends EventEmitter {
|
|||||||
*/
|
*/
|
||||||
_onResponseReceived(event) {
|
_onResponseReceived(event) {
|
||||||
let request = this._idToRequest.get(event.requestId) || null;
|
let request = this._idToRequest.get(event.requestId) || null;
|
||||||
let response = new Response(request, event.response);
|
let response = new Response(request, event.response, this._getResponseBody.bind(this, event.requestId));
|
||||||
request._response = response;
|
request._response = response;
|
||||||
this.emit(NetworkManager.Events.Response, response);
|
this.emit(NetworkManager.Events.Response, response);
|
||||||
}
|
}
|
||||||
@@ -131,6 +131,15 @@ class NetworkManager extends EventEmitter {
|
|||||||
this._idToRequest.delete(event.requestId);
|
this._idToRequest.delete(event.requestId);
|
||||||
this.emit(NetworkManager.Events.RequestFailed, request);
|
this.emit(NetworkManager.Events.RequestFailed, request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} requestId
|
||||||
|
* @return {!Promise<!Buffer>}
|
||||||
|
*/
|
||||||
|
async _getResponseBody(requestId) {
|
||||||
|
let response = await this._client.send('Network.getResponseBody', {requestId});
|
||||||
|
return Buffer.from(response.body, response.base64Encoded ? 'base64' : 'utf8');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Headers {
|
class Headers {
|
||||||
@@ -218,11 +227,63 @@ class Headers {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Request {
|
class Body {
|
||||||
|
/**
|
||||||
|
* @param {function():!Promise<!Buffer>} contentCallback
|
||||||
|
*/
|
||||||
|
constructor(contentCallback) {
|
||||||
|
this._contentCallback = contentCallback;
|
||||||
|
/** @type {?Promise<!Buffer>} */
|
||||||
|
this._contentPromise = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {!Promise<!Buffer>}
|
||||||
|
*/
|
||||||
|
buffer() {
|
||||||
|
if (!this._contentPromise)
|
||||||
|
this._contentPromise = this._contentCallback();
|
||||||
|
return this._contentPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
get bodyUsed() {
|
||||||
|
return !!this._contentPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {!Promise<string>}
|
||||||
|
*/
|
||||||
|
async text() {
|
||||||
|
let content = await this.buffer();
|
||||||
|
return content.toString('utf8');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {!Promise<!Object>}
|
||||||
|
*/
|
||||||
|
async json() {
|
||||||
|
let content = await this.text();
|
||||||
|
return JSON.parse(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {!Promise<!ArrayBuffer>}
|
||||||
|
*/
|
||||||
|
async arrayBuffer() {
|
||||||
|
let content = await this.buffer();
|
||||||
|
return content.buffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Request extends Body {
|
||||||
/**
|
/**
|
||||||
* @param {!Object} payload
|
* @param {!Object} payload
|
||||||
*/
|
*/
|
||||||
constructor(payload) {
|
constructor(payload) {
|
||||||
|
super(() => Promise.resolve(payload.postData || ''));
|
||||||
this._response = null;
|
this._response = null;
|
||||||
this.url = payload.url;
|
this.url = payload.url;
|
||||||
this.method = payload.method;
|
this.method = payload.method;
|
||||||
@@ -238,12 +299,14 @@ class Request {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Response {
|
class Response extends Body {
|
||||||
/**
|
/**
|
||||||
* @param {?Request} request
|
* @param {?Request} request
|
||||||
* @param {!Object} payload
|
* @param {!Object} payload
|
||||||
|
* @param {function():!Promise<!Buffer>} contentCallback
|
||||||
*/
|
*/
|
||||||
constructor(request, payload) {
|
constructor(request, payload, contentCallback) {
|
||||||
|
super(contentCallback);
|
||||||
this._request = request;
|
this._request = request;
|
||||||
this.headers = Headers.fromPayload(payload.headers);
|
this.headers = Headers.fromPayload(payload.headers);
|
||||||
this.ok = payload.status >= 200 && payload.status <= 299;
|
this.ok = payload.status >= 200 && payload.status <= 299;
|
||||||
|
|||||||
1
test/assets/simple.json
Normal file
1
test/assets/simple.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"foo": "bar"}
|
||||||
28
test/test.js
28
test/test.js
@@ -37,8 +37,8 @@ describe('Puppeteer', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
afterAll(function() {
|
afterAll(function() {
|
||||||
browser.close();
|
|
||||||
staticServer.stop();
|
staticServer.stop();
|
||||||
|
browser.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(SX(async function() {
|
beforeEach(SX(async function() {
|
||||||
@@ -526,6 +526,32 @@ describe('Puppeteer', function() {
|
|||||||
expect(result).toBe('<div>hello</div>');
|
expect(result).toBe('<div>hello</div>');
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
describe('Request implements Body', function() {
|
||||||
|
it('should work', SX(async function() {
|
||||||
|
await page.navigate(EMPTY_PAGE);
|
||||||
|
staticServer.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.bodyUsed).toBe(false);
|
||||||
|
expect(await request.text()).toBe('{"foo":"bar"}');
|
||||||
|
expect(await request.json()).toEqual({foo: 'bar'});
|
||||||
|
expect(request.bodyUsed).toBe(true);
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
describe('Response implements Body', function() {
|
||||||
|
it('should work', SX(async function() {
|
||||||
|
let response = null;
|
||||||
|
page.on('response', r => response = r);
|
||||||
|
await page.navigate(STATIC_PREFIX + '/simple.json');
|
||||||
|
expect(response).toBeTruthy();
|
||||||
|
expect(response.bodyUsed).toBe(false);
|
||||||
|
expect(await response.text()).toBe('{"foo": "bar"}\n');
|
||||||
|
expect(await response.json()).toEqual({foo: 'bar'});
|
||||||
|
expect(response.bodyUsed).toBe(true);
|
||||||
|
}));
|
||||||
|
});
|
||||||
describe('Network Events', function() {
|
describe('Network Events', function() {
|
||||||
it('Page.Events.Request', SX(async function() {
|
it('Page.Events.Request', SX(async function() {
|
||||||
let requests = [];
|
let requests = [];
|
||||||
|
|||||||
Reference in New Issue
Block a user