-
Notifications
You must be signed in to change notification settings - Fork 2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
op-reg: Switch from
node-fetch
to make-fetch-happen
.
This is a similar treatment as to what was applied to `@apollo/gateway` in #3783. This replaces a "fetcher" implementation we'd been maintaining (which continues to grow in complexity) which was built on [`node-fetch`][1]. Instead, it switches to an off-the-shelf [Fetch API][2]-compliant implementation called [`make-fetch-happen`][3] which leverages [`minipass-fetch`][4] under the hood. It's also what `npm` uses internally! Whereas `node-fetch` is relatively bare-bones and necessitated us writing our own [conditional request][5], `make-fetch-happen` just does these things (and also other things, like supporting `HTTP_PROXY` out of the box!). It does, however, need us to provide a cache store since we cannot use its (default) file-system based cache (which leverages the powerful [`cacache`][6] implementation used by `npm`) since file-systems are not available in all of our supported integrations. Therefore, this duplicates the same cache implementation used in `@apollo/gateway`. If there was a suitable place to depend on this code from both of these packages, we could depend on this implementation from that location, but I didn't immediately see a great place for that to live. Also, rule of threes or something? (Also worth noting that it _already includes_ the fix which I opened in #4325 / 2f29c60 which needed to be applied to the gateway implementation.) This does REMOVE A TEST which was previously valuable but should no longer be nearly as valuable. Specifically, since we now have an HTTP implementation that handles conditional requests, a cache, and retries itself, we do handle intermediary retries within that layer. We still test the polling (i.e, the literal existence of an interval which re-fires) in other tests, but it was too tricky to try to re-jigger this test with the abstraction. I think this is a good thing to not need to worry about, but we can consider re-adding it in the event of regressions. [1]: https://npm.im/node-fetch [2]: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API [3]: https://npm.im/make-fetch-happen [4]: https://npm.im/minipass-fetch [5]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Conditional_requests [6]: https://npm.im/cacache
- Loading branch information
Showing
8 changed files
with
449 additions
and
91 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
4 changes: 4 additions & 0 deletions
4
packages/apollo-server-plugin-operation-registry/CHANGELOG.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
66 changes: 66 additions & 0 deletions
66
packages/apollo-server-plugin-operation-registry/src/cache.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import { CacheManager } from 'make-fetch-happen'; | ||
import { Request, Response, Headers } from 'apollo-server-env'; | ||
import { InMemoryLRUCache } from 'apollo-server-caching'; | ||
|
||
const MAX_SIZE = 5 * 1024 * 1024; // 5MB | ||
|
||
function cacheKey(request: Request) { | ||
return `op-reg:request-cache:${request.method}:${request.url}`; | ||
} | ||
|
||
interface CachedRequest { | ||
body: string; | ||
status: number; | ||
statusText: string; | ||
headers: Headers; | ||
} | ||
|
||
export class HttpRequestCache implements CacheManager { | ||
constructor( | ||
public cache: InMemoryLRUCache<CachedRequest> = new InMemoryLRUCache({ | ||
maxSize: MAX_SIZE, | ||
}), | ||
) {} | ||
|
||
// Return true if entry exists, else false | ||
async delete(request: Request) { | ||
const key = cacheKey(request); | ||
const entry = await this.cache.get(key); | ||
await this.cache.delete(key); | ||
return Boolean(entry); | ||
} | ||
|
||
async put(request: Request, response: Response) { | ||
// A `HEAD` request has no body to cache and a 304 response could have | ||
// only been negotiated by using a cached body that was still valid. | ||
// Therefore, we do NOT write to the cache in either of these cases. | ||
// Without avoiding this, we will invalidate the cache, thus causing | ||
// subsequent conditional requests (e.g., `If-None-Match: "MD%") to be | ||
// lacking content to conditionally request against and necessitating | ||
// a full request/response. | ||
if (request.method === "HEAD" || response.status === 304) { | ||
return response; | ||
} | ||
|
||
const body = await response.text(); | ||
|
||
this.cache.set(cacheKey(request), { | ||
body, | ||
status: response.status, | ||
statusText: response.statusText, | ||
headers: response.headers, | ||
}); | ||
|
||
return new Response(body, response); | ||
} | ||
|
||
async match(request: Request) { | ||
return this.cache.get(cacheKey(request)).then(response => { | ||
if (response) { | ||
const { body, ...requestInit } = response; | ||
return new Response(body, requestInit); | ||
} | ||
return; | ||
}); | ||
} | ||
} |
21 changes: 0 additions & 21 deletions
21
packages/apollo-server-plugin-operation-registry/src/fetchIfNoneMatch.ts
This file was deleted.
Oops, something went wrong.