Skip to content

Commit

Permalink
Make it possible to pass custom fetch to rest data source (#1807)
Browse files Browse the repository at this point in the history
* 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 <mcdonald.emily@live.co.uk>

* Lint fix
  • Loading branch information
Jae Anne Bach Hardie authored and hwillson committed Jul 9, 2019
1 parent d028ebf commit 12da96d
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ the query extensions' `clientInfo` values will be used. [PR #1960](https://githu
- Azure functions support [Issue #1752](https://github.com/apollographql/apollo-server/issue/1752) [PR #1753](https://github.com/apollographql/apollo-server/pull/1753) [PR #1948](https://github.com/apollographql/apollo-server/pull/1948)
- Allow JSON parsing in `RESTDataSource` of Content Type `application/hal+json`. [PR #185](https://github.com/apollographql/apollo-server/pull/1853)
- Add support for a `requestAgent` configuration parameter within the `engine` configuration. This can be utilized when a proxy is necessary to transmit tracing and metrics data to Apollo Engine. It accepts either an [`http.Agent`](https://nodejs.org/docs/latest-v8.x/api/http.html#http_class_http_agent) or [`https.Agent`](https://nodejs.org/docs/latest-v8.x/api/https.html#https_class_https_agent) and behaves the same as the `agent` parameter to Node.js' [`http.request`](https://nodejs.org/docs/latest-v8.x/api/http.html#http_http_request_options_callback). [PR #1879](https://github.com/apollographql/apollo-server/pull/1879)
- 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

Expand Down
12 changes: 9 additions & 3 deletions packages/apollo-datasource-rest/src/HTTPCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,17 @@ import { CacheOptions } from './RESTDataSource';

export class HTTPCache {
private keyValueCache: KeyValueCache;
constructor(keyValueCache: KeyValueCache = new InMemoryLRUCache()) {
private httpFetch: typeof fetch;

constructor(
keyValueCache: KeyValueCache = new InMemoryLRUCache(),
httpFetch: typeof fetch = fetch,
) {
this.keyValueCache = new PrefixingKeyValueCache(
keyValueCache,
'httpcache:',
);
this.httpFetch = httpFetch;
}

async fetch(
Expand All @@ -31,7 +37,7 @@ export class HTTPCache {

const entry = await this.keyValueCache.get(cacheKey);
if (!entry) {
const response = await fetch(request);
const response = await this.httpFetch(request);

const policy = new CachePolicy(
policyRequestFrom(request),
Expand Down Expand Up @@ -71,7 +77,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),
Expand Down
7 changes: 6 additions & 1 deletion packages/apollo-datasource-rest/src/RESTDataSource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
URL,
URLSearchParams,
URLSearchParamsInit,
fetch,
ValueOrPromise,
} from 'apollo-server-env';

Expand Down Expand Up @@ -47,9 +48,13 @@ export abstract class RESTDataSource<TContext = any> extends DataSource {
context!: TContext;
memoizedResults = new Map<string, Promise<any>>();

constructor(private httpFetch?: typeof fetch) {
super();
}

initialize(config: DataSourceConfig<TContext>): void {
this.context = config.context;
this.httpCache = new HTTPCache(config.cache);
this.httpCache = new HTTPCache(config.cache, this.httpFetch);
}

baseURL?: string;
Expand Down
14 changes: 14 additions & 0 deletions packages/apollo-datasource-rest/src/__tests__/HTTPCache.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -459,4 +459,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' });
});
});

0 comments on commit 12da96d

Please sign in to comment.