deno.land / x / ky@v0.31.3 / test / retry.ts
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443import test from 'ava';import ky from '../source/index.js';import {createHttpTestServer} from './helpers/create-http-test-server.js';
const fixture = 'fixture';const defaultRetryCount = 2;const retryAfterOn413 = 2;const lastTried413access = Date.now();
test('network error', async t => { let requestCount = 0;
const server = await createHttpTestServer(); server.get('/', (_request, response) => { requestCount++;
if (requestCount === defaultRetryCount) { response.end(fixture); } else { response.status(99_999).end(); } });
t.is(await ky(server.url).text(), fixture);
await server.close();});
test('status code 500', async t => { let requestCount = 0;
const server = await createHttpTestServer(); server.get('/', (_request, response) => { requestCount++;
if (requestCount === defaultRetryCount) { response.end(fixture); } else { response.sendStatus(500); } });
t.is(await ky(server.url).text(), fixture);
await server.close();});
test('only on defined status codes', async t => { let requestCount = 0;
const server = await createHttpTestServer(); server.get('/', (_request, response) => { requestCount++;
if (requestCount === defaultRetryCount) { response.end(fixture); } else { response.sendStatus(400); } });
await t.throwsAsync(ky(server.url).text(), {message: /Bad Request/});
await server.close();});
test('not on POST', async t => { let requestCount = 0;
const server = await createHttpTestServer(); server.post('/', (_request, response) => { requestCount++;
if (requestCount === defaultRetryCount) { response.end(fixture); } else { response.sendStatus(500); } });
await t.throwsAsync(ky.post(server.url).text(), { message: /Internal Server Error/, });
await server.close();});
test('respect 413 Retry-After', async t => { let requestCount = 0;
const server = await createHttpTestServer(); server.get('/', (_request, response) => { requestCount++;
if (requestCount === defaultRetryCount) { response.end((Date.now() - lastTried413access).toString()); } else { response.writeHead(413, { 'Retry-After': retryAfterOn413, }); response.end(''); } });
const result = await ky(server.url).text(); t.true(Number(result) >= retryAfterOn413 * 1000);
await server.close();});
test('respect 413 Retry-After with timestamp', async t => { let requestCount = 0;
const server = await createHttpTestServer({bodyParser: false}); server.get('/', (_request, response) => { requestCount++; if (requestCount === defaultRetryCount) { response.end((Date.now() - lastTried413access).toString()); } else { // @NOTE we need to round up to the next second due to http-date resolution const date = new Date(Date.now() + ((retryAfterOn413 + 1) * 1000)).toUTCString(); response.writeHead(413, { 'Retry-After': date, }); response.end(''); } });
const result = await ky(server.url).text(); t.true(Number(result) >= retryAfterOn413 * 1000); t.is(requestCount, 2);
await server.close();});
test('doesn\'t retry on 413 without Retry-After header', async t => { let requestCount = 0;
const server = await createHttpTestServer(); server.get('/', (_request, response) => { requestCount++; response.sendStatus(413); });
await t.throwsAsync(ky(server.url).text(), {message: /Payload Too Large/}); t.is(requestCount, 1); await ky(server.url, {throwHttpErrors: false}).text(); t.is(requestCount, 2);
await server.close();});
test('respect number of retries', async t => { let requestCount = 0;
const server = await createHttpTestServer(); server.get('/', (_request, response) => { requestCount++; response.sendStatus(408); });
await t.throwsAsync( ky(server.url, { retry: { limit: 3, }, }).text(), { message: /Request Timeout/, }, ); t.is(requestCount, 3);
await server.close();});
test('respect retry methods', async t => { let requestCount = 0;
const server = await createHttpTestServer(); server.post('/', (_request, response) => { requestCount++; response.sendStatus(408); });
server.get('/', (_request, response) => { requestCount++; response.sendStatus(408); });
await t.throwsAsync( ky(server.url, { method: 'post', retry: { limit: 3, methods: ['get'], }, }).text(), { message: /Request Timeout/, }, ); t.is(requestCount, 1);
requestCount = 0; await t.throwsAsync( ky(server.url, { retry: { limit: 3, methods: ['get'], }, }).text(), { message: /Request Timeout/, }, ); t.is(requestCount, 3);
await server.close();});
test('respect maxRetryAfter', async t => { let requestCount = 0;
const server = await createHttpTestServer(); server.get('/', async (_request, response) => { requestCount++;
response.writeHead(413, { 'Retry-After': 1, });
response.end(''); });
await t.throwsAsync( ky(server.url, { retry: { limit: 5, maxRetryAfter: 100, }, }).text(), { message: /Payload Too Large/, }, ); t.is(requestCount, 1);
requestCount = 0; await t.throwsAsync( ky(server.url, { retry: { limit: 5, maxRetryAfter: 2000, }, }).text(), { message: /Payload Too Large/, }, ); t.is(requestCount, 5);
await server.close();});
test('retry - can provide retry as number', async t => { let requestCount = 0;
const server = await createHttpTestServer(); server.get('/', async (_request, response) => { requestCount++; response.sendStatus(408); });
await t.throwsAsync(ky(server.url, {retry: 5}).text(), { message: /Request Timeout/, }); t.is(requestCount, 5);
await server.close();});
test('doesn\'t retry on 413 with empty statusCodes and methods', async t => { let requestCount = 0;
const server = await createHttpTestServer();
server.get('/', async (_request, response) => { requestCount++; response.sendStatus(413); });
await t.throwsAsync( ky(server.url, { retry: { limit: 10, statusCodes: [], methods: [], }, }).text(), { message: /Payload Too Large/, }, );
t.is(requestCount, 1);
await server.close();});
test('doesn\'t retry on 413 with empty methods', async t => { let requestCount = 0;
const server = await createHttpTestServer(); server.get('/', async (_request, response) => { requestCount++; response.sendStatus(413); });
await t.throwsAsync( ky(server.url, { retry: { limit: 10, methods: [], }, }).text(), { message: /Payload Too Large/, }, );
t.is(requestCount, 1);
await server.close();});
test('does retry on 408 with methods provided as array', async t => { let requestCount = 0;
const server = await createHttpTestServer(); server.get('/', async (_request, response) => { requestCount++; response.sendStatus(408); });
await t.throwsAsync( ky(server.url, { retry: { limit: 4, methods: ['get'], }, }).text(), { message: /Request Timeout/, }, );
t.is(requestCount, 4);
await server.close();});
test('does retry on 408 with statusCodes provided as array', async t => { let requestCount = 0;
const server = await createHttpTestServer(); server.get('/', async (_request, response) => { requestCount++; response.sendStatus(408); });
await t.throwsAsync( ky(server.url, { retry: { limit: 4, statusCodes: [408], }, }).text(), { message: /Request Timeout/, }, );
t.is(requestCount, 4);
await server.close();});
test('doesn\'t retry when retry.limit is set to 0', async t => { let requestCount = 0;
const server = await createHttpTestServer(); server.get('/', (_request, response) => { requestCount++; response.sendStatus(408); });
await t.throwsAsync( ky(server.url, { retry: { limit: 0, }, }).text(), { message: /Request Timeout/, }, );
t.is(requestCount, 1);
await server.close();});
test('throws when retry.methods is not an array', async t => { const server = await createHttpTestServer();
t.throws(() => { void ky(server.url, { retry: { // @ts-expect-error methods: 'get', }, }); });
await server.close();});
test('throws when retry.statusCodes is not an array', async t => { const server = await createHttpTestServer();
t.throws(() => { void ky(server.url, { retry: { // @ts-expect-error statusCodes: 403, }, }); });
await server.close();});
Version Info