Skip to content
Open
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
75 changes: 75 additions & 0 deletions test/fetch/http2.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict'

const { createSecureServer } = require('node:http2')
const { createServer } = require('node:http')
const { createReadStream, readFileSync } = require('node:fs')
const { once } = require('node:events')
const { Readable } = require('node:stream')
Expand Down Expand Up @@ -504,3 +505,77 @@ test('Issue #3046', async (t) => {
t.assert.strictEqual(response.headers.get('content-type'), 'text/html; charset=utf-8')
t.assert.deepStrictEqual(response.headers.getSetCookie(), ['hello=world', 'foo=bar'])
})

// The two following tests expose a discrepancy of behavior when enabling HTTP/2.
// Without H2 enabled, empty POST requests have a Content-Length of 0 specified.
// With H2 enabled, empty POST requests do not have a Content-Length header.
// The RFC 9110 (see https://httpwg.org/specs/rfc9110.html#field.content-length)
// states it SHOULD have one, so that is not mandatory, but is there a good reason
// for not having it?
test('[Fetch] Empty POST without h2 has Content-Length', async (t) => {
const server = createServer({ joinDuplicateHeaders: true }, (req, res) => {
res.statusCode = 200
res.end(`content-length:${req.headers['content-length']}`)
}).listen(0)

const client = new Client(`http://localhost:${server.address().port}`)

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

t.plan(1)

await once(server, 'listening')

const response = await fetch(
`http://localhost:${server.address().port}/`, {
method: 'POST',
dispatcher: client
}
)

const responseBody = await response.text()
t.assert.strictEqual(responseBody, `content-length:${0}`)
})

test('[Fetch] Empty POST with h2 has no Content-Length', async (t) => {
const server = createSecureServer(await pem.generate({ opts: { keySize: 2048 } }))

server.on('stream', async (stream, headers) => {
stream.respond({
'content-type': 'text/plain; charset=utf-8',
':status': 200
})

stream.end(`content-length:${headers['content-length']}`)
})

t.plan(1)

server.listen()
await once(server, 'listening')

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

t.after(closeClientAndServerAsPromise(client, server))

const response = await fetch(
`https://localhost:${server.address().port}/`,
// Needs to be passed to disable the reject unauthorized
{
method: 'POST',
dispatcher: client
}
)

const responseBody = await response.text()

t.assert.strictEqual(responseBody, `content-length:${undefined}`)
})
Loading