From a5dbc2160ac86b326948295be624255d172ef526 Mon Sep 17 00:00:00 2001 From: AMS777 <32177639+AMS777@users.noreply.github.com> Date: Mon, 26 Mar 2018 18:34:06 +0200 Subject: [PATCH 1/3] Add json parse when the request is 'application/x-www-form-urlencoded'. The current json parse is only valid for requests of type 'application/json', so a valid parse for requests of type 'application/x-www-form-urlencoded' is added. --- addon/lib/json-utils.js | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/addon/lib/json-utils.js b/addon/lib/json-utils.js index b98ba26..43f8f3b 100644 --- a/addon/lib/json-utils.js +++ b/addon/lib/json-utils.js @@ -7,10 +7,24 @@ export function stringifyJSON(json={}){ export function jsonFromRequest(request){ let json = {}; if (request.requestBody) { + // nested try...catch statements to avoid complexity checking the content + // type from the headers, as key and value may have multiple formats: + // - Key: 'content-type', 'Content-Type'. + // - Value: 'application/json', 'application/vnd.api+json'. try { + // 'Content-Type': 'application/json' json = JSON.parse(request.requestBody); - } catch(e) { - Ember.Logger.warn(`[FakeServer] Failed to parse json from request.requestBody "${request.requestBody}" (error: ${e})`); + } catch (e) { + try { + // 'Content-Type': 'application/x-www-form-urlencoded' + json = JSON.parse( + '{"' + + decodeURIComponent(request.requestBody.replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g,'":"')) + + '"}' + ); + } catch(e) { + Ember.Logger.warn(`[FakeServer] Failed to parse json from request.requestBody "${request.requestBody}" (error: ${e})`); + } } } From 651fe79ccbf64c27ab092ebb7d3f94d517e2609a Mon Sep 17 00:00:00 2001 From: AMS777 <32177639+AMS777@users.noreply.github.com> Date: Mon, 26 Mar 2018 19:43:18 +0200 Subject: [PATCH 2/3] Fix JSHint error "Misleading line break before '+'". Fix JSHint error: "modules/ember-cli-fake-server/lib/json-utils.js: line 22, col 11, Misleading line break before '+'; readers may interpret this as an expression boundary." --- addon/lib/json-utils.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/addon/lib/json-utils.js b/addon/lib/json-utils.js index 43f8f3b..09ac513 100644 --- a/addon/lib/json-utils.js +++ b/addon/lib/json-utils.js @@ -17,11 +17,7 @@ export function jsonFromRequest(request){ } catch (e) { try { // 'Content-Type': 'application/x-www-form-urlencoded' - json = JSON.parse( - '{"' - + decodeURIComponent(request.requestBody.replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g,'":"')) - + '"}' - ); + json = JSON.parse('{"' + decodeURIComponent(request.requestBody.replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g,'":"')) + '"}'); } catch(e) { Ember.Logger.warn(`[FakeServer] Failed to parse json from request.requestBody "${request.requestBody}" (error: ${e})`); } From 298bb0771596f9e01910cae31159da1e8ec2e7eb Mon Sep 17 00:00:00 2001 From: AMS777 Date: Mon, 9 Apr 2018 19:39:44 +0200 Subject: [PATCH 3/3] Identify x-www-form-urlencoded requests to parse the attributes as JSON. --- addon/lib/json-utils.js | 40 +++++++++++++++++++++-------- tests/unit/fake-server-test.js | 46 ++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 11 deletions(-) diff --git a/addon/lib/json-utils.js b/addon/lib/json-utils.js index 09ac513..e3497c7 100644 --- a/addon/lib/json-utils.js +++ b/addon/lib/json-utils.js @@ -7,18 +7,12 @@ export function stringifyJSON(json={}){ export function jsonFromRequest(request){ let json = {}; if (request.requestBody) { - // nested try...catch statements to avoid complexity checking the content - // type from the headers, as key and value may have multiple formats: - // - Key: 'content-type', 'Content-Type'. - // - Value: 'application/json', 'application/vnd.api+json'. - try { - // 'Content-Type': 'application/json' - json = JSON.parse(request.requestBody); - } catch (e) { + if (contentTypeHeaderIsFormUrlEncoded(request.requestHeaders)) { + json = getJsonFromFormUrlEncodedRequest(request.requestBody); + } else { try { - // 'Content-Type': 'application/x-www-form-urlencoded' - json = JSON.parse('{"' + decodeURIComponent(request.requestBody.replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g,'":"')) + '"}'); - } catch(e) { + json = JSON.parse(request.requestBody); + } catch (e) { Ember.Logger.warn(`[FakeServer] Failed to parse json from request.requestBody "${request.requestBody}" (error: ${e})`); } } @@ -26,3 +20,27 @@ export function jsonFromRequest(request){ return json; } + +function contentTypeHeaderIsFormUrlEncoded(requestHeaders) { + // request headers string example: + // {"Content-Type":"application/x-www-form-urlencoded","Accept":"*/*","X-Requested-With":"XMLHttpRequest"} + const caseInsensitiveformUrlEncodedContentTypeHeader = /content-type[":' ]+application\/x-www-form-urlencoded/gi; + const contentTypeHeaderStringToCheckCaseInsensitive = JSON.stringify(requestHeaders); + const contentTypeHeaderIsFormUrlEncoded = + caseInsensitiveformUrlEncodedContentTypeHeader.test(contentTypeHeaderStringToCheckCaseInsensitive); + + return contentTypeHeaderIsFormUrlEncoded; +} + +function getJsonFromFormUrlEncodedRequest(requestBody) { + let json = {}; + try { + // 'application/x-www-form-urlencoded' request body example: + // "foo=bar&hello=World!" + json = JSON.parse('{"' + decodeURIComponent(requestBody.replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g,'":"')) + '"}'); + } catch(e) { + Ember.Logger.warn(`[FakeServer] Failed to parse json from request.requestBody "${requestBody}" (error: ${e})`); + } + + return json; +} diff --git a/tests/unit/fake-server-test.js b/tests/unit/fake-server-test.js index 06642d8..4a46e23 100644 --- a/tests/unit/fake-server-test.js +++ b/tests/unit/fake-server-test.js @@ -89,6 +89,52 @@ test('#json reads JSON in request payload', (assert) => { }); }); +test('json() function parses x-www-form-urlencoded request payload', (assert) => { + let done = assert.async(); + assert.expect(1); + + const jsonPayload = { + foo: 'bar', + hello: 'World!', + }; + const urlEncodedPayload = "foo=bar&hello=World!"; + + stubRequest('post', '/blah', (request) => { + assert.deepEqual(request.json(), jsonPayload, 'POST payload'); + request.noContent(); + }); + + jQuery.ajax('/blah', { + type: 'POST', + data: urlEncodedPayload, + contentType: 'application/x-www-form-urlencoded', + complete: done + }); +}); + +test('json() function parses x-www-form-urlencoded request payload with special characters', (assert) => { + let done = assert.async(); + assert.expect(1); + + const jsonPayload = { + foo: 'bar', + password: '$€áÉîÖùñÑ', + }; + const urlEncodedPayload = "foo=bar&password=$€áÉîÖùñÑ"; + + stubRequest('post', '/blah', (request) => { + assert.deepEqual(request.json(), jsonPayload, 'POST payload'); + request.noContent(); + }); + + jQuery.ajax('/blah', { + type: 'POST', + data: urlEncodedPayload, + contentType: 'application/x-www-form-urlencoded', + complete: done + }); +}); + test('FakeServer.config.afterResponse can modify responses', (assert) => { let done = assert.async(); assert.expect(6);