Fix: Serialize arrays as JSON on fetch in RESTDataSource (#2219)

Fixes issue introduced in https://github.com/apollographql/apollo-server/pull/1125 and logged in https://github.com/apollographql/apollo-server/issues/2186 and https://github.com/apollographql/apollo-server/issues/2196.

Arrays are valid JSON per spec: https://tools.ietf.org/html/rfc7159
This commit is contained in:
Jesse Rosenberger 2019-02-05 14:28:44 +02:00 committed by GitHub
commit 8b1b3d795b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 29 additions and 1 deletions

View file

@ -2,6 +2,8 @@
### vNEXT
- Fix: Serialize arrays as JSON on fetch in `RESTDataSource`. [PR #2219](https://github.com/apollographql/apollo-server/pull/2219)
### v2.3.3
- `apollo-server` (only): Stop double-invocation of `serverWillStart` life-cycle event. (More specific integrations - e.g. Express, Koa, Hapi, etc. - were unaffected.) [PR #2239](https://github.com/apollographql/apollo-server/pull/2239)

View file

@ -218,11 +218,12 @@ export abstract class RESTDataSource<TContext = any> extends DataSource {
url.searchParams.append(name, value);
}
// We accept arbitrary objects as body and serialize them as JSON
// We accept arbitrary objects and arrays as body and serialize them as JSON
if (
options.body !== undefined &&
options.body !== null &&
(options.body.constructor === Object ||
Array.isArray(options.body) ||
((options.body as any).toJSON &&
typeof (options.body as any).toJSON === 'function'))
) {

View file

@ -268,6 +268,31 @@ describe('RESTDataSource', () => {
);
});
it('serializes a request body that is an array as JSON', async () => {
const dataSource = new class extends RESTDataSource {
baseURL = 'https://api.example.com';
postFoo(foo) {
return this.post('foo', foo);
}
}();
dataSource.httpCache = httpCache;
fetch.mockJSONResponseOnce();
await dataSource.postFoo(['foo', 'bar']);
expect(fetch.mock.calls.length).toEqual(1);
expect(fetch.mock.calls[0][0].url).toEqual('https://api.example.com/foo');
expect(fetch.mock.calls[0][0].body).toEqual(
JSON.stringify(['foo', 'bar']),
);
expect(fetch.mock.calls[0][0].headers.get('Content-Type')).toEqual(
'application/json',
);
});
it('serializes a request body that has a toJSON method as JSON', async () => {
const dataSource = new class extends RESTDataSource {
baseURL = 'https://api.example.com';