Skip to content

Commit

Permalink
fix: sending formdata bodies with http2 (#3863) [backport] (#3866)
Browse files Browse the repository at this point in the history
* fix: sending formdata bodies with http2 (#3863)

(cherry picked from commit e49b575)

* fix: bad merge

---------

Co-authored-by: Khafra <[email protected]>
  • Loading branch information
metcoder95 and KhafraDev authored Nov 22, 2024
1 parent a0220f1 commit ee6176c
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 2 deletions.
15 changes: 14 additions & 1 deletion lib/dispatcher/client-h2.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ const {

const kOpenStreams = Symbol('open streams')

let extractBody

// Experimental
let h2ExperimentalWarned = false

Expand Down Expand Up @@ -260,7 +262,8 @@ function shouldSendContentLength (method) {

function writeH2 (client, request) {
const session = client[kHTTP2Session]
const { body, method, path, host, upgrade, expectContinue, signal, headers: reqHeaders } = request
const { method, path, host, upgrade, expectContinue, signal, headers: reqHeaders } = request
let { body } = request

if (upgrade) {
util.errorRequest(client, request, new Error('Upgrade not supported for H2'))
Expand Down Expand Up @@ -381,6 +384,16 @@ function writeH2 (client, request) {

let contentLength = util.bodyLength(body)

if (util.isFormDataLike(body)) {
extractBody ??= require('../web/fetch/body.js').extractBody

const [bodyStream, contentType] = extractBody(body)
headers['content-type'] = contentType

body = bodyStream.stream
contentLength = bodyStream.length
}

if (contentLength == null) {
contentLength = request.contentLength
}
Expand Down
53 changes: 52 additions & 1 deletion test/http2.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const { Writable, pipeline, PassThrough, Readable } = require('node:stream')

const pem = require('https-pem')

const { Client, Agent } = require('..')
const { Client, Agent, FormData } = require('..')

const isGreaterThanv20 = process.versions.node.split('.').map(Number)[0] >= 20

Expand Down Expand Up @@ -1442,3 +1442,54 @@ test('#3671 - Graceful close', async (t) => {

await t.completed
})

test('#3803 - sending FormData bodies works', async (t) => {
const assert = tspl(t, { plan: 4 })

const server = createSecureServer(pem).listen(0)
server.on('stream', async (stream, headers) => {
const contentLength = Number(headers['content-length'])

assert.ok(!Number.isNaN(contentLength))
assert.ok(headers['content-type']?.startsWith('multipart/form-data; boundary='))

stream.respond({ ':status': 200 })

const fd = await new Response(stream, {
headers: {
'content-type': headers['content-type']
}
}).formData()

assert.deepEqual(fd.get('a'), 'b')
assert.deepEqual(fd.get('c').name, 'e.fgh')

stream.end()
})

await once(server, 'listening')

const client = new Client(`https://localhost:${server.address().port}`, {
connect: {
rejectUnauthorized: false
},
allowH2: true
})

t.after(async () => {
server.close()
await client.close()
})

const fd = new FormData()
fd.set('a', 'b')
fd.set('c', new Blob(['d']), 'e.fgh')

await client.request({
path: '/',
method: 'POST',
body: fd
})

await assert.completed
})

0 comments on commit ee6176c

Please sign in to comment.