diff --git a/source/core/index.ts b/source/core/index.ts index 88b886620..a46d91858 100644 --- a/source/core/index.ts +++ b/source/core/index.ts @@ -987,16 +987,24 @@ export default class Request extends Duplex implements RequestEvents { let request: ClientRequest | Promise; - // This is ugly - const cacheRequest = cacheableStore.get((options as any).cache)!(options, async response => { - // TODO: Fix `cacheable-response` - (response as any)._readableState.autoDestroy = false; + // TODO: Fix `cacheable-response`. This is ugly. + const cacheRequest = cacheableStore.get((options as any).cache)!(options, async (response: any) => { + response._readableState.autoDestroy = false; if (request) { + const fix = () => { + if (response.req) { + response.complete = response.req.res.complete; + } + }; + + response.prependOnceListener('end', fix); + fix(); + (await request).emit('cacheableResponse', response); } - resolve(response as unknown as ResponseLike); + resolve(response); }); cacheRequest.once('error', reject); diff --git a/test/cache.ts b/test/cache.ts index 729f8771b..407d3a1d6 100644 --- a/test/cache.ts +++ b/test/cache.ts @@ -1,4 +1,5 @@ import {promisify} from 'util'; +import {Agent} from 'http'; import {gzip} from 'zlib'; import test from 'ava'; import pEvent from 'p-event'; @@ -403,3 +404,40 @@ test('allows internal modifications', async t => { await t.notThrowsAsync(client.get('http://example.com/test')); }); + +test('response.complete is true when using keepalive agent', withServer, async (t, server, got) => { + const agent = { + http: new Agent({keepAlive: true}) + }; + + const etag = 'foobar'; + + const payload = JSON.stringify({foo: 'bar'}); + const compressed = await promisify(gzip)(payload); + + server.get('/', (request, response) => { + if (request.headers['if-none-match'] === etag) { + response.statusCode = 304; + response.end(); + } else { + response.setHeader('content-encoding', 'gzip'); + response.setHeader('cache-control', 'public, max-age=60'); + response.setHeader('etag', etag); + response.end(compressed); + } + }); + + const cache = new Map(); + + const first = await got({ + cache, + responseType: 'json', + decompress: true, + retry: { + limit: 2 + }, + agent + }); + + t.true(first.complete); +});