From b01e10c31ede6677eb0143be91d7be304f7c8f48 Mon Sep 17 00:00:00 2001 From: Jae Anne Bach Hardie Date: Fri, 12 Oct 2018 11:33:10 +0100 Subject: [PATCH 1/2] Added functionality to pass custom fetch to rest data source This is an optional constructor parameter. If a custom fetch function is not defined, the default fetch will be used. This new functionality has been covered in the http cache tests. Co-Authored-By: Emily McDonald --- CHANGELOG.md | 1 + packages/apollo-datasource-rest/src/HTTPCache.ts | 9 ++++++--- .../apollo-datasource-rest/src/RESTDataSource.ts | 7 ++++++- .../src/__tests__/HTTPCache.test.ts | 14 ++++++++++++++ 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d82ba35e11c..440f2439278 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - Allow an optional function to resolve the `rootValue`, passing the `DocumentNode` AST to determine the value. [PR #1555](https://github.com/apollographql/apollo-server/pull/1555) - Follow-up on the work in [PR #1516](https://github.com/apollographql/apollo-server/pull/1516) to also fix missing insertion cursor/caret when a custom GraphQL configuration is specified which doesn't specify its own `cursorShape` property. [PR #1607](https://github.com/apollographql/apollo-server/pull/1607) +- Allow an optional parameter to the `RESTDataSource` constructor which takes a `node-fetch`-compatible `fetch` implementation that will be used for HTTP calls instead of the default fetch. [PR #1807](https://github.com/apollographql/apollo-server/pull/1807) ### v2.1.0 diff --git a/packages/apollo-datasource-rest/src/HTTPCache.ts b/packages/apollo-datasource-rest/src/HTTPCache.ts index 1b7da5e3f96..153cf89c669 100644 --- a/packages/apollo-datasource-rest/src/HTTPCache.ts +++ b/packages/apollo-datasource-rest/src/HTTPCache.ts @@ -6,7 +6,10 @@ import { KeyValueCache, InMemoryLRUCache } from 'apollo-server-caching'; import { CacheOptions } from './RESTDataSource'; export class HTTPCache { - constructor(private keyValueCache: KeyValueCache = new InMemoryLRUCache()) {} + constructor( + private keyValueCache: KeyValueCache = new InMemoryLRUCache(), + private httpFetch: typeof fetch = fetch, + ) {} async fetch( request: Request, @@ -21,7 +24,7 @@ export class HTTPCache { const entry = await this.keyValueCache.get(`httpcache:${cacheKey}`); if (!entry) { - const response = await fetch(request); + const response = await this.httpFetch(request); const policy = new CachePolicy( policyRequestFrom(request), @@ -61,7 +64,7 @@ export class HTTPCache { const revalidationRequest = new Request(request, { headers: revalidationHeaders, }); - const revalidationResponse = await fetch(revalidationRequest); + const revalidationResponse = await this.httpFetch(revalidationRequest); const { policy: revalidatedPolicy, modified } = policy.revalidatedPolicy( policyRequestFrom(revalidationRequest), diff --git a/packages/apollo-datasource-rest/src/RESTDataSource.ts b/packages/apollo-datasource-rest/src/RESTDataSource.ts index 59b068768e6..aa95f80f9dc 100644 --- a/packages/apollo-datasource-rest/src/RESTDataSource.ts +++ b/packages/apollo-datasource-rest/src/RESTDataSource.ts @@ -7,6 +7,7 @@ import { URL, URLSearchParams, URLSearchParamsInit, + fetch, } from 'apollo-server-env'; import { DataSource, DataSourceConfig } from 'apollo-datasource'; @@ -48,9 +49,13 @@ export abstract class RESTDataSource extends DataSource { context!: TContext; memoizedResults = new Map>(); + constructor(private httpFetch?: typeof fetch) { + super(); + } + initialize(config: DataSourceConfig): void { this.context = config.context; - this.httpCache = new HTTPCache(config.cache); + this.httpCache = new HTTPCache(config.cache, this.httpFetch); } baseURL?: string; diff --git a/packages/apollo-datasource-rest/src/__tests__/HTTPCache.test.ts b/packages/apollo-datasource-rest/src/__tests__/HTTPCache.test.ts index 3935a667861..72849304ecb 100644 --- a/packages/apollo-datasource-rest/src/__tests__/HTTPCache.test.ts +++ b/packages/apollo-datasource-rest/src/__tests__/HTTPCache.test.ts @@ -452,4 +452,18 @@ describe('HTTPCache', () => { expect(await response2.json()).toEqual({ name: 'Alan Turing' }); expect(response2.headers.get('Age')).toEqual('10'); }); + + it('fetches a response from the origin with a custom fetch function', async () => { + fetch.mockJSONResponseOnce({ name: 'Ada Lovelace' }); + + const customFetch = jest.fn(fetch); + const customHttpCache = new HTTPCache(store as any, customFetch); + + const response = await customHttpCache.fetch( + new Request('https://api.example.com/people/1'), + ); + + expect(customFetch.mock.calls.length).toEqual(1); + expect(await response.json()).toEqual({ name: 'Ada Lovelace' }); + }); }); From 77a1312d15f0cd3a22bccab025e915fee4f08686 Mon Sep 17 00:00:00 2001 From: hwillson Date: Mon, 8 Jul 2019 17:01:17 -0700 Subject: [PATCH 2/2] Lint fix --- packages/apollo-datasource-rest/src/HTTPCache.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/apollo-datasource-rest/src/HTTPCache.ts b/packages/apollo-datasource-rest/src/HTTPCache.ts index 0337869e083..c9d3a217cb0 100644 --- a/packages/apollo-datasource-rest/src/HTTPCache.ts +++ b/packages/apollo-datasource-rest/src/HTTPCache.ts @@ -15,7 +15,7 @@ export class HTTPCache { constructor( keyValueCache: KeyValueCache = new InMemoryLRUCache(), - httpFetch: typeof fetch = fetch + httpFetch: typeof fetch = fetch, ) { this.keyValueCache = new PrefixingKeyValueCache( keyValueCache,