Skip to content
Merged
Show file tree
Hide file tree
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
2 changes: 1 addition & 1 deletion src/middleware/web-outgoing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export const writeHeaders = defineProxyOutgoingMiddleware((req, res, proxyRes, o
const preserveHeaderKeyCase = options.preserveHeaderKeyCase;
let rawHeaderKeyMap: Record<string, string> | undefined;
const setHeader = function (key: string, header: string | string[] | undefined) {
if (header === undefined) {
if (header === undefined || !String(key).trim()) {
return;
}
if (rewriteCookieDomainConfig && key.toLowerCase() === "set-cookie") {
Expand Down
31 changes: 31 additions & 0 deletions test/middleware/web-outgoing.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -651,7 +651,7 @@
const res = {
setHeader(k: string, v: string | string[]) {
// Simulate Node.js ERR_INVALID_CHAR for control characters
if (typeof v === "string" && /[\u0000-\u001F]/.test(v)) {

Check warning on line 654 in test/middleware/web-outgoing.test.ts

View workflow job for this annotation

GitHub Actions / checks

eslint(no-control-regex)

Unexpected control characters

Check warning on line 654 in test/middleware/web-outgoing.test.ts

View workflow job for this annotation

GitHub Actions / autofix

eslint(no-control-regex)

Unexpected control characters

Check warning on line 654 in test/middleware/web-outgoing.test.ts

View workflow job for this annotation

GitHub Actions / autofix

eslint(no-control-regex)

Unexpected control characters

Check warning on line 654 in test/middleware/web-outgoing.test.ts

View workflow job for this annotation

GitHub Actions / checks

eslint(no-control-regex)

Unexpected control characters
throw new TypeError(`Invalid character in header content ["${k}"]`);
}
headers[k.toLowerCase()] = v;
Expand All @@ -668,6 +668,37 @@
expect(headers).to.not.have.key("invalid-header");
});

it("skips empty header names (upstream#1551)", () => {
const proxyRes = {
headers: {
"": "empty-key-value",
" ": "whitespace-key-value",
hey: "hello",
},
};
const headers: Record<string, any> = {};
const res = {
setHeader(k: string, v: string | string[]) {
// Simulate Node.js ERR_INVALID_HTTP_TOKEN for empty/invalid header names
if (!k || !/^[\w!#$%&'*+\-.^`|~]+$/.test(k)) {
throw new TypeError(`Header name must be a valid HTTP token ["${k}"]`);
}
headers[k.toLowerCase()] = v;
},
};
webOutgoing.writeHeaders(
stubIncomingMessage(),
res as any,
proxyRes as any,
stubMiddlewareOptions(),
);
// Valid headers should still be set
expect(headers.hey).to.eql("hello");
// Empty/whitespace-only header names should be skipped
expect(headers).to.not.have.key("");
expect(headers).to.not.have.key(" ");
});

it("skips undefined header values", () => {
const proxyRes = {
headers: {
Expand Down
Loading