Skip to content

Commit

Permalink
fix: undici headers (#289)
Browse files Browse the repository at this point in the history
* fix: undici headers

* test: fix multiple listen

* test: provide undici option

* test: use keepAliveMaxTimeout 10

* chore: update comment

Co-authored-by: Simen Bekkhus <[email protected]>

---------

Co-authored-by: Simen Bekkhus <[email protected]>
  • Loading branch information
climba03003 and SimenB authored Feb 2, 2023
1 parent b30a4fe commit 09cb8e7
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 2 deletions.
4 changes: 2 additions & 2 deletions lib/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const querystring = require('querystring')
const eos = require('end-of-stream')
const pump = require('pump')
const undici = require('undici')
const { stripHttp1ConnectionHeaders } = require('./utils')
const { patchUndiciHeaders, stripHttp1ConnectionHeaders } = require('./utils')
const http2 = require('http2')

const {
Expand Down Expand Up @@ -158,7 +158,7 @@ function buildRequest (opts) {
// using delete, otherwise it will render as an empty string
delete res.headers['transfer-encoding']

done(null, { statusCode: res.statusCode, headers: res.headers, stream: res.body })
done(null, { statusCode: res.statusCode, headers: patchUndiciHeaders(res.headers), stream: res.body })
})
}

Expand Down
26 changes: 26 additions & 0 deletions lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,31 @@ function filterPseudoHeaders (headers) {
return dest
}

// http requires the header to be encoded with latin1
// undici will convert the latin1 buffer to utf8
// https://github.com/nodejs/undici/blob/2b260c997ad4efe4ed2064b264b4b546a59e7a67/lib/core/util.js#L216-L229
// after chaining, the header will be serialised using wrong encoding
// Buffer.from('', 'latin1').toString('utf8') applied
//
// in order to persist the encoding, always encode it
// back to latin1
function patchUndiciHeaders (headers) {
const headersKeys = Object.keys(headers)
const dist = {}

let header
let i

for (i = 0; i < headersKeys.length; i++) {
header = headersKeys[i]
if (header.charCodeAt(0) !== 58) { // fast path for indexOf(':') === 0
dist[header] = Buffer.from(headers[header]).toString('latin1')
}
}

return dist
}

function copyHeaders (headers, reply) {
const headersKeys = Object.keys(headers)

Expand Down Expand Up @@ -74,6 +99,7 @@ function buildURL (source, reqBase) {
}

module.exports = {
patchUndiciHeaders,
copyHeaders,
stripHttp1ConnectionHeaders,
filterPseudoHeaders,
Expand Down
57 changes: 57 additions & 0 deletions test/undici-chaining.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
'use strict'

const t = require('tap')
const Fastify = require('fastify')
const get = require('simple-get').concat
const From = require('..')

const header = 'attachment; filename="år.pdf"'

t.plan(6)

const instance = Fastify()
t.teardown(instance.close.bind(instance))
const proxy1 = Fastify()
t.teardown(proxy1.close.bind(proxy1))
const proxy2 = Fastify()
t.teardown(proxy2.close.bind(proxy2))

instance.get('/', (request, reply) => {
reply.header('content-disposition', header).send('OK')
})

proxy1.register(From, {
undici: {
keepAliveMaxTimeout: 10
}
})
proxy1.get('/', (request, reply) => {
return reply.from(`http://localhost:${instance.server.address().port}`)
})

proxy2.register(From, {
undici: {
keepAliveMaxTimeout: 10
}
})
proxy2.get('/', (request, reply) => {
return reply.from(`http://localhost:${proxy1.server.address().port}`)
})

instance.listen({ port: 0 }, err => {
t.error(err)

proxy1.listen({ port: 0 }, err => {
t.error(err)

proxy2.listen({ port: 0 }, err => {
t.error(err)

get(`http://localhost:${proxy2.server.address().port}`, (err, res, data) => {
t.error(err)
t.equal(res.statusCode, 200)
t.equal(data.toString(), 'OK')
})
})
})
})

0 comments on commit 09cb8e7

Please sign in to comment.