Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions fetch.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,65 @@ t.test('Retrying', async t => {
await res.blob()
t.equal(res.headers.get('received-id'), 'foo')
})

t.test('Response available in retry function', async t => {
let capturedResponse = null

const server = fastify()
server.get('/test-response', (_request, reply) => {
// Always return a 500 error with some headers
reply.status(500)
reply.header('x-error-code', 'TEMP_ERROR')
reply.header('x-request-id', '12345')
reply.send({error: 'Server error'})
})

await server.listen({port: 0})
const address = server.server.address()
const serverPort = typeof address === 'object' ? address?.port : null

try {
await t.rejects(
fetch(`http://localhost:${serverPort}/test-response`, {
validate: true, // This will cause the 500 to throw an error
retry: async ({error: _error, response}) => {
capturedResponse = response

// Verify we can access response and its properties
t.ok(response, 'Response should be available in retry function')
if (response) {
t.equal(
response.status,
500,
'Should have access to response status'
)
t.equal(
response.headers.get('x-error-code'),
'TEMP_ERROR',
'Should have access to response headers'
)
t.equal(
response.headers.get('x-request-id'),
'12345',
'Should have access to custom headers'
)
}

// Don't retry - we just want to test that response is available
return false
},
}),
'Should reject with HttpError'
)

t.ok(
capturedResponse,
'Should have captured the response in retry function'
)
} finally {
await server.close()
}
})
})

t.test(`Providing custom abort signal`, async t => {
Expand Down
5 changes: 3 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,7 @@ const fetch = async (resource, options, state) => {
state.size = undefined
state[STATE_INTERNAL].timedout = undefined
state[STATE_INTERNAL].validateStarted = false
let /** @type {FetchResponse | undefined} */ response
try {
prepareOptions(state)
const {
Expand All @@ -333,7 +334,7 @@ const fetch = async (resource, options, state) => {
)

state.startTs = performance.now()
let response = /** @type {FetchResponse} */ (
response = /** @type {FetchResponse} */ (
await origFetch(state.resource, currOptions)
)
const {body, status} = response
Expand Down Expand Up @@ -377,7 +378,7 @@ const fetch = async (resource, options, state) => {
// Here we catch request errors only
state[STATE_INTERNAL].clearAbort?.('request')
dbg(`${state.fullId} failed`, error)
if (await shouldRetry({state, error})) {
if (await shouldRetry({state, error, response})) {
continue
}
state[STATE_INTERNAL].signalCompleted(error)
Expand Down