Skip to content

Commit

Permalink
fix casing issue when cloning Headers object
Browse files Browse the repository at this point in the history
Refs: nodejs#3159 (comment)

Co-authored-by: tsctx <[email protected]>
  • Loading branch information
KhafraDev and tsctx committed Apr 24, 2024
1 parent ad81122 commit 0862ebe
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 2 deletions.
6 changes: 6 additions & 0 deletions lib/web/fetch/headers.js
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,12 @@ webidl.converters.HeadersInit = function (V) {
if (webidl.util.Type(V) === 'Object') {
const iterator = Reflect.get(V, Symbol.iterator)

// A work-around to ensure we send the properly-cased Headers when V is a Headers object.
// Read https://github.com/nodejs/undici/pull/3159#issuecomment-2075537226 before touching, please.
if (!util.types.isProxy(V) && kHeadersList in V && iterator === Headers.prototype.entries) { // Headers object
return V[kHeadersList].entries
}

if (typeof iterator === 'function') {
return webidl.converters['sequence<sequence<ByteString>>'](V, iterator.bind(V))
}
Expand Down
5 changes: 3 additions & 2 deletions lib/web/fetch/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -459,8 +459,9 @@ class Request {
// 4. If headers is a Headers object, then for each header in its header
// list, append header’s name/header’s value to this’s headers.
if (headers instanceof HeadersList) {
for (const [key, val] of headers) {
headersList.append(key, val)
for (const { 0: key, 1: val } of headers) {
// Note: The header names are already in lowercase.
headersList.append(key, val, true)
}
// Note: Copy the `set-cookie` meta-data.
headersList.cookies = headers.cookies
Expand Down
31 changes: 31 additions & 0 deletions test/fetch/headers-case.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
'use strict'

const { fetch, Headers } = require('../..')
const { createServer } = require('node:http')
const { once } = require('node:events')
const { test } = require('node:test')
const { tspl } = require('@matteo.collina/tspl')

test('Headers retain keys case-sensitive', async (t) => {
const assert = tspl(t, { plan: 3 })

const server = createServer((req, res) => {
console.log(req.rawHeaders)
assert.ok(req.rawHeaders.includes('Content-Type'))

res.end()
}).listen(0)

t.after(() => server.close())
await once(server, 'listening')

for (const headers of [
new Headers([['Content-Type', 'text/plain']]),
{ 'Content-Type': 'text/plain' },
[['Content-Type', 'text/plain']]
]) {
await fetch(`http://localhost:${server.address().port}`, {
headers
})
}
})

0 comments on commit 0862ebe

Please sign in to comment.