From 9dfe9348acd92a2da8a2e19a70d4e0fe185c0df3 Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Thu, 28 May 2020 03:43:49 +0200 Subject: [PATCH] feat: Request.postDataJSON (#2368) --- docs/api.md | 6 ++++++ src/network.ts | 20 ++++++++++++++++++++ test/network.spec.js | 28 ++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+) diff --git a/docs/api.md b/docs/api.md index ae81fcf859..d21a9b6a3b 100644 --- a/docs/api.md +++ b/docs/api.md @@ -3499,6 +3499,7 @@ If request gets a 'redirect' response, the request is successfully finished with - [request.isNavigationRequest()](#requestisnavigationrequest) - [request.method()](#requestmethod) - [request.postData()](#requestpostdata) +- [request.postDataJSON()](#requestpostdatajson) - [request.redirectedFrom()](#requestredirectedfrom) - [request.redirectedTo()](#requestredirectedto) - [request.resourceType()](#requestresourcetype) @@ -3538,6 +3539,11 @@ Whether this request is driving frame's navigation. #### request.postData() - returns: Request's post body, if any. +#### request.postDataJSON() +- returns: Parsed request's body for `form-urlencoded` and JSON as a fallback if any. + +When the response is `application/x-www-form-urlencoded` then a key/value object of the values will be returned. Otherwise it will be parsed as JSON. + #### request.redirectedFrom() - returns: Request that was redirected by the server to this one, if any. diff --git a/src/network.ts b/src/network.ts index a4ea7a3c3e..8216f49e6a 100644 --- a/src/network.ts +++ b/src/network.ts @@ -20,6 +20,7 @@ import * as util from 'util'; import * as frames from './frames'; import { assert, helper } from './helper'; import { Page } from './page'; +import { URLSearchParams } from 'url'; export type NetworkCookie = { name: string, @@ -153,6 +154,25 @@ export class Request { return this._postData; } + postDataJSON(): Object | null { + if (!this._postData) + return null; + + const contentType = this.headers()['content-type']; + if (!contentType) + return null; + + if (contentType === 'application/x-www-form-urlencoded') { + const entries: Record = {}; + const parsed = new URLSearchParams(this._postData); + for (const [k, v] of parsed.entries()) + entries[k] = v; + return entries; + } + + return JSON.parse(this._postData); + } + headers(): {[key: string]: string} { return { ...this._headers }; } diff --git a/test/network.spec.js b/test/network.spec.js index 91367d8abb..f539e87234 100644 --- a/test/network.spec.js +++ b/test/network.spec.js @@ -140,6 +140,34 @@ describe('Request.postData', function() { }); }); +describe('Request.postDataJSON', function () { + it('should parse the JSON payload', async ({ page, server }) => { + await page.goto(server.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.postDataJSON()).toEqual({ "foo": "bar" }); + }); + + it('should parse the data if content-type is application/x-www-form-urlencoded', async({page, server}) => { + await page.goto(server.EMPTY_PAGE); + server.setRoute('/post', (req, res) => res.end()); + let request = null; + page.on('request', r => request = r); + await page.setContent(`
`); + await page.click('input[type=submit]'); + expect(request).toBeTruthy(); + expect(request.postDataJSON()).toEqual({'foo':'bar','baz':'123'}); + }) + + it('should be |undefined| when there is no post data', async ({ page, server }) => { + const response = await page.goto(server.EMPTY_PAGE); + expect(response.request().postDataJSON()).toBe(null); + }); +}); + describe('Response.text', function() { it('should work', async({page, server}) => { const response = await page.goto(server.PREFIX + '/simple.json');