Skip to content

Commit e49b68d

Browse files
authored
fix(fetch): connection is cancelled when redirecting (nodejs#1787)
1 parent bb84264 commit e49b68d

File tree

3 files changed

+34
-2
lines changed

3 files changed

+34
-2
lines changed

lib/fetch/index.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -781,8 +781,11 @@ async function mainFetch (fetchParams, recursive = false) {
781781
// https://fetch.spec.whatwg.org/#concept-scheme-fetch
782782
// given a fetch params fetchParams
783783
async function schemeFetch (fetchParams) {
784+
// Note: since the connection is destroyed on redirect, which sets fetchParams to a
785+
// cancelled state, we do not want this condition to trigger *unless* there have been
786+
// no redirects. See https://github.com/nodejs/undici/issues/1776
784787
// 1. If fetchParams is canceled, then return the appropriate network error for fetchParams.
785-
if (isCancelled(fetchParams)) {
788+
if (isCancelled(fetchParams) && fetchParams.request.redirectCount === 0) {
786789
return makeAppropriateNetworkError(fetchParams)
787790
}
788791

lib/fetch/response.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,7 @@ function makeAppropriateNetworkError (fetchParams) {
436436
// otherwise return a network error.
437437
return isAborted(fetchParams)
438438
? makeNetworkError(new DOMException('The operation was aborted.', 'AbortError'))
439-
: makeNetworkError(fetchParams.controller.terminated.reason)
439+
: makeNetworkError('Request was cancelled.')
440440
}
441441

442442
// https://whatpr.org/fetch/1392.html#initialize-a-response

test/fetch/redirect.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
'use strict'
2+
3+
const { test } = require('tap')
4+
const { createServer } = require('http')
5+
const { once } = require('events')
6+
const { fetch } = require('../..')
7+
8+
// https://github.com/nodejs/undici/issues/1776
9+
test('Redirecting with a body does not cancel the current request - #1776', async (t) => {
10+
const server = createServer((req, res) => {
11+
if (req.url === '/redirect') {
12+
res.statusCode = 301
13+
res.setHeader('location', '/redirect/')
14+
res.write('<a href="/redirect/">Moved Permanently</a>')
15+
setTimeout(() => res.end(), 500)
16+
return
17+
}
18+
19+
res.write(req.url)
20+
res.end()
21+
}).listen(0)
22+
23+
t.teardown(server.close.bind(server))
24+
await once(server, 'listening')
25+
26+
const resp = await fetch(`http://localhost:${server.address().port}/redirect`)
27+
t.equal(await resp.text(), '/redirect/')
28+
t.ok(resp.redirected)
29+
})

0 commit comments

Comments
 (0)