Skip to content

Commit d7707ee

Browse files
authored
fix: handle FormData body type correctly in RetryAgent retried requests (#4692)
1 parent 7e5cb2d commit d7707ee

File tree

2 files changed

+73
-0
lines changed

2 files changed

+73
-0
lines changed

lib/core/util.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ function wrapRequestBody (body) {
5858
// to determine whether or not it has been disturbed. This is just
5959
// a workaround.
6060
return new BodyAsyncIterable(body)
61+
} else if (body && isFormDataLike(body)) {
62+
return body
6163
} else if (
6264
body &&
6365
typeof body !== 'string' &&

test/issue-4691.js

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
'use strict'
2+
3+
const { tspl } = require('@matteo.collina/tspl')
4+
const { test, after } = require('node:test')
5+
const { createServer } = require('node:http')
6+
const { once } = require('node:events')
7+
8+
const { RetryAgent, Client, FormData } = require('..')
9+
// https://github.com/nodejs/undici/issues/4691
10+
test('Should retry status code with FormData body', async t => {
11+
t = tspl(t, { plan: 2 })
12+
13+
let counter = 0
14+
const server = createServer({ joinDuplicateHeaders: true })
15+
const opts = {
16+
maxRetries: 5,
17+
timeout: 1,
18+
timeoutFactor: 1
19+
}
20+
21+
server.on('request', (req, res) => {
22+
switch (counter++) {
23+
case 0:
24+
req.destroy()
25+
return
26+
case 1:
27+
res.writeHead(500)
28+
res.end('failed')
29+
return
30+
case 2:
31+
res.writeHead(200)
32+
res.end('hello world!')
33+
return
34+
default:
35+
t.fail()
36+
}
37+
})
38+
39+
server.listen(0, () => {
40+
const client = new Client(`http://localhost:${server.address().port}`)
41+
const agent = new RetryAgent(client, opts)
42+
43+
after(async () => {
44+
await agent.close()
45+
server.close()
46+
47+
await once(server, 'close')
48+
})
49+
50+
const formData = new FormData()
51+
formData.append('field', 'test string')
52+
agent.request({
53+
method: 'GET',
54+
path: '/',
55+
headers: {
56+
'content-type': 'application/json'
57+
},
58+
body: formData
59+
}).then((res) => {
60+
t.equal(res.statusCode, 200)
61+
res.body.setEncoding('utf8')
62+
let chunks = ''
63+
res.body.on('data', chunk => { chunks += chunk })
64+
res.body.on('end', () => {
65+
t.equal(chunks, 'hello world!')
66+
})
67+
})
68+
})
69+
70+
await t.completed
71+
})

0 commit comments

Comments
 (0)