Skip to content

Commit 0d06552

Browse files
authored
fix: 301 and 302 change method to GET (#3862)
1 parent 6551919 commit 0d06552

File tree

4 files changed

+22
-10
lines changed

4 files changed

+22
-10
lines changed

lib/handler/redirect-handler.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ const redirectableStatusCodes = [300, 301, 302, 303, 307, 308]
1010

1111
const kBody = Symbol('body')
1212

13+
const noop = () => {}
14+
1315
class BodyAsyncIterable {
1416
constructor (body) {
1517
this[kBody] = body
@@ -132,10 +134,20 @@ class RedirectHandler {
132134
this.opts.maxRedirections = 0
133135
this.opts.query = null
134136

137+
// https://tools.ietf.org/html/rfc7231#section-6.4.2
138+
// https://fetch.spec.whatwg.org/#http-redirect-fetch
139+
// In case of HTTP 301 or 302 with POST, change the method to GET
140+
if ((statusCode === 301 || statusCode === 302) && this.opts.method === 'POST') {
141+
this.opts.method = 'GET'
142+
if (util.isStream(this.opts.body)) util.destroy(this.opts.body.on('error', noop))
143+
this.opts.body = null
144+
}
145+
135146
// https://tools.ietf.org/html/rfc7231#section-6.4.4
136147
// In case of HTTP 303, always replace method to be either HEAD or GET
137148
if (statusCode === 303 && this.opts.method !== 'HEAD') {
138149
this.opts.method = 'GET'
150+
if (util.isStream(this.opts.body)) util.destroy(this.opts.body.on('error', noop))
139151
this.opts.body = null
140152
}
141153
}

test/interceptors/redirect.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ for (const factory of [
167167
await t.completed
168168
})
169169

170-
test('should follow redirection after a HTTP 301', async t => {
170+
test('should follow redirection after a HTTP 301 changing method to GET', async t => {
171171
t = tspl(t, { plan: 3 })
172172

173173
const server = await startRedirectingServer()
@@ -188,7 +188,7 @@ for (const factory of [
188188
t.ok(!headers.location)
189189
t.strictEqual(
190190
body,
191-
`POST /5 :: host@${server} connection@keep-alive content-length@7 :: REQUEST`
191+
`GET /5 :: host@${server} connection@keep-alive`
192192
)
193193
})
194194

@@ -540,7 +540,7 @@ for (const factory of [
540540
headers,
541541
body: bodyStream
542542
} = await request(t, server, undefined, `http://${server}/301`, {
543-
method: 'POST',
543+
method: 'PUT',
544544
body: createReadableStream('REQUEST'),
545545
maxRedirections: 10
546546
})
@@ -608,7 +608,7 @@ test('should follow redirections when going cross origin', async t => {
608608
`http://${server1}/end`
609609
]
610610
)
611-
t.strictEqual(body, 'POST')
611+
t.strictEqual(body, 'GET')
612612

613613
await t.completed
614614
})

test/redirect-request.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ for (const factory of [
125125

126126
t.strictEqual(statusCode, 200)
127127
t.ok(!headers.location)
128-
t.strictEqual(body, `POST /5 :: host@${server} connection@keep-alive content-length@7 :: REQUEST`)
128+
t.strictEqual(body, `GET /5 :: host@${server} connection@keep-alive`)
129129
})
130130

131131
test('should follow redirection after a HTTP 302', async t => {
@@ -485,7 +485,7 @@ for (const factory of [
485485
const server = await startRedirectingServer()
486486

487487
const { statusCode, headers, body: bodyStream } = await request(t, server, undefined, `http://${server}/301`, {
488-
method: 'POST',
488+
method: 'PUT',
489489
body: createReadableStream('REQUEST'),
490490
maxRedirections: 10
491491
})
@@ -541,7 +541,7 @@ test('should follow redirections when going cross origin', async t => {
541541
`http://${server3}/end`,
542542
`http://${server1}/end`
543543
])
544-
t.strictEqual(body, 'POST')
544+
t.strictEqual(body, 'GET')
545545

546546
await t.completed
547547
})

test/redirect-stream.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ test('should follow redirection after a HTTP 300', async t => {
8080
t.strictEqual(body.join(''), `GET /5 key=value :: host@${server} connection@keep-alive`)
8181
})
8282

83-
test('should follow redirection after a HTTP 301', async t => {
83+
test('should follow redirection after a HTTP 301 changing method to GET', async t => {
8484
t = tspl(t, { plan: 3 })
8585

8686
const body = []
@@ -97,7 +97,7 @@ test('should follow redirection after a HTTP 301', async t => {
9797
}
9898
)
9999

100-
t.strictEqual(body.join(''), `POST /5 :: host@${server} connection@keep-alive content-length@7 :: REQUEST`)
100+
t.strictEqual(body.join(''), `GET /5 :: host@${server} connection@keep-alive`)
101101
})
102102

103103
test('should follow redirection after a HTTP 302', async t => {
@@ -316,7 +316,7 @@ test('should follow redirections when going cross origin', async t => {
316316
}
317317
)
318318

319-
t.strictEqual(body.join(''), 'POST')
319+
t.strictEqual(body.join(''), 'GET')
320320
})
321321

322322
describe('when a Location response header is NOT present', async () => {

0 commit comments

Comments
 (0)