Skip to content

Commit ffbed40

Browse files
committed
fix(node): do not url-encode upgrade response headers
`sendResponse` was passing header keys and values through `encodeURIComponent`, mangling legitimate values like `WWW-Authenticate: Bearer realm="crossws"`. Write them verbatim. Closes #186
1 parent 86fb6f1 commit ffbed40

File tree

4 files changed

+7
-7
lines changed

4 files changed

+7
-7
lines changed

src/adapters/node.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -219,10 +219,7 @@ class NodeReqProxy extends StubRequest {
219219
async function sendResponse(socket: Duplex, res: Response) {
220220
const head = [
221221
`HTTP/1.1 ${res.status || 200} ${res.statusText || ""}`,
222-
...[...res.headers.entries()].map(
223-
([key, value]) =>
224-
`${encodeURIComponent(key)}: ${encodeURIComponent(value)}`,
225-
),
222+
...[...res.headers.entries()].map(([key, value]) => `${key}: ${value}`),
226223
];
227224
socket.write(head.join("\r\n") + "\r\n\r\n");
228225
if (res.body) {

test/_utils.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,7 @@ class WebSocketInspector extends Agent {
126126
const out: Record<string, string> = {};
127127
if (!headers) return out;
128128
for (const [key, value] of Object.entries(headers)) {
129-
const joined = Array.isArray(value) ? value.join(", ") : value;
130-
out[decodeURIComponent(key).toLowerCase()] = decodeURIComponent(joined);
129+
out[key.toLowerCase()] = Array.isArray(value) ? value.join(", ") : value;
131130
}
132131
return out;
133132
}

test/fixture/_shared.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,10 @@ export function createDemo<T extends Adapter<any, any>>(
6969
return new Response("unauthorized", {
7070
status: 401,
7171
statusText: "Unauthorized",
72-
headers: { "x-error": "unauthorized" },
72+
headers: {
73+
"x-error": "unauthorized",
74+
"www-authenticate": 'Bearer realm="crossws"',
75+
},
7376
});
7477
},
7578
};

test/tests.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ export function wsTests(getURL: () => string, opts: WSTestOpts): void {
149149
headers: {
150150
"content-type": expect.stringMatching(/^text\/plain/),
151151
"x-error": "unauthorized",
152+
"www-authenticate": 'Bearer realm="crossws"',
152153
},
153154
});
154155
});

0 commit comments

Comments
 (0)