From 4c05b2562447fb192d134b2eba9ed0867ddf6771 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Escolano?= Date: Fri, 27 Sep 2019 11:53:35 +0200 Subject: [PATCH 1/3] Refactor headers management for fetchJson --- packages/ra-core/src/util/fetch.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/ra-core/src/util/fetch.ts b/packages/ra-core/src/util/fetch.ts index 9db09fd2bdd..494256fa12b 100644 --- a/packages/ra-core/src/util/fetch.ts +++ b/packages/ra-core/src/util/fetch.ts @@ -8,7 +8,7 @@ interface Options extends RequestInit { }; } -export const fetchJson = (url, options: Options = {}) => { +export const createHeadersFromOptions = (options: Options): Headers => { const requestHeaders = (options.headers || new Headers({ Accept: 'application/json', @@ -23,6 +23,12 @@ export const fetchJson = (url, options: Options = {}) => { requestHeaders.set('Authorization', options.user.token); } + return requestHeaders; +}; + +export const fetchJson = (url, options: Options = {}) => { + const requestHeaders = createHeadersFromOptions(options); + return fetch(url, { ...options, headers: requestHeaders }) .then(response => response.text().then(text => ({ From 1284bab9602f86aa0d2328f822a6d204035e5ec7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Escolano?= Date: Fri, 27 Sep 2019 11:59:25 +0200 Subject: [PATCH 2/3] Add Content-Type header only for non GET requests. --- packages/ra-core/src/util/fetch.spec.ts | 32 ++++++++++++++++++++++++- packages/ra-core/src/util/fetch.ts | 1 + 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/packages/ra-core/src/util/fetch.spec.ts b/packages/ra-core/src/util/fetch.spec.ts index 2f7b7f08eae..b8bf9bc4c93 100644 --- a/packages/ra-core/src/util/fetch.spec.ts +++ b/packages/ra-core/src/util/fetch.spec.ts @@ -1,5 +1,9 @@ import assert from 'assert'; -import { queryParameters, flattenObject } from './fetch'; +import { + createHeadersFromOptions, + queryParameters, + flattenObject, +} from './fetch'; describe('queryParameters', () => { it('should generate a query parameter', () => { @@ -57,3 +61,29 @@ describe('flattenObject', () => { assert.deepEqual(flattenObject(input), expected); }); }); + +describe('createHeadersFromOptions', () => { + it('should add a Content-Type header for POST requests', () => { + const options = { + method: 'POST', + }; + + const headers = createHeadersFromOptions(options); + assert.strictEqual(headers.get('Content-Type'), 'application/json'); + }); + + it('should not add a Content-Type header for GET requests', () => { + const optionsWithoutMethod = {}; + const optionsWithMethod = { + method: 'GET', + }; + + const headersWithMethod = createHeadersFromOptions(optionsWithMethod); + assert.strictEqual(headersWithMethod.get('Content-Type'), null); + + const headersWithoutMethod = createHeadersFromOptions( + optionsWithoutMethod + ); + assert.strictEqual(headersWithoutMethod.get('Content-Type'), null); + }); +}); diff --git a/packages/ra-core/src/util/fetch.ts b/packages/ra-core/src/util/fetch.ts index 494256fa12b..d656529674e 100644 --- a/packages/ra-core/src/util/fetch.ts +++ b/packages/ra-core/src/util/fetch.ts @@ -15,6 +15,7 @@ export const createHeadersFromOptions = (options: Options): Headers => { })) as Headers; if ( !requestHeaders.has('Content-Type') && + !(options && (!options.method || options.method === 'GET')) && !(options && options.body && options.body instanceof FormData) ) { requestHeaders.set('Content-Type', 'application/json'); From 7bcdd9e97182d3c822218f9bd69b624bb76a3a15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Escolano?= Date: Fri, 27 Sep 2019 13:48:41 +0200 Subject: [PATCH 3/3] Mock fetch Headers to make tests work --- package.json | 3 ++- test-setup.js | 10 ++++++++++ yarn.lock | 2 +- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 8165fbf520a..e5ad1b27794 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,8 @@ "prettier": "~1.17.1", "raf": "~3.4.0", "ts-jest": "^23.10.5", - "wait-on": "^2.1.0" + "wait-on": "^2.1.0", + "whatwg-fetch": "^3.0.0" }, "workspaces": [ "packages/*", diff --git a/test-setup.js b/test-setup.js index a552cd44b6d..75c36b2d37e 100644 --- a/test-setup.js +++ b/test-setup.js @@ -45,3 +45,13 @@ jest.mock('popper.js', () => { ]; return Popper; }); + +/** + * Mock fetch objects Response, Request and Headers + */ + +const { Response, Headers, Request } = require('whatwg-fetch'); + +global.Response = Response; +global.Headers = Headers; +global.Request = Request; diff --git a/yarn.lock b/yarn.lock index 0d512c1f14d..357c98f456c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -16035,7 +16035,7 @@ whatwg-encoding@^1.0.3, whatwg-encoding@^1.0.5: dependencies: iconv-lite "0.4.24" -whatwg-fetch@3.0.0: +whatwg-fetch@3.0.0, whatwg-fetch@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#fc804e458cc460009b1a2b966bc8817d2578aefb" integrity sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==