Skip to content

Commit

Permalink
Respect headers from transport option nodeOptions.headers (#1219)
Browse files Browse the repository at this point in the history
  • Loading branch information
timostamm authored Sep 9, 2024
1 parent 6d375c1 commit ed63cee
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 26 deletions.
3 changes: 1 addition & 2 deletions packages/connect-node/src/node-universal-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,13 +130,12 @@ function createNodeHttp1Client(
sentinel.catch((e) => {
reject(e);
});

h1Request(
sentinel,
req.url,
{
...httpOptions,
headers: webHeaderToNodeHeaders(req.header),
headers: webHeaderToNodeHeaders(req.header, httpOptions?.headers),
method: req.method,
},
(request) => {
Expand Down
21 changes: 21 additions & 0 deletions packages/connect-node/src/node-universal-header.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import * as http from "http";
import {
nodeHeaderToWebHeader,
webHeaderToNodeHeaders,
Expand Down Expand Up @@ -124,4 +125,24 @@ describe("webHeaderToNodeHeaders()", function () {
});
});
}
it("should accept default node headers", function () {
const nodeDefaults: http.OutgoingHttpHeaders = {
a: "a",
b: ["b1", "b2"],
c: 123,
};
const webHeaders: HeadersInit = [
["b", "web"],
["c", "456"],
["d", "d1"],
["d", "d2"],
];
const h = webHeaderToNodeHeaders(webHeaders, nodeDefaults);
expect(h).toEqual({
a: "a",
b: ["b1", "b2", "web"],
c: ["123", "456"],
d: ["d1", "d2"],
});
});
});
69 changes: 45 additions & 24 deletions packages/connect-node/src/node-universal-header.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,45 +53,66 @@ export function nodeHeaderToWebHeader(

/**
* Convert a fetch API Headers object to a Node.js headers object.
*
* Optionally accepts default Node.js headers. If provided, fetch API headers
* are appended to the defaults. The original defaults headers are not modified.
*/
export function webHeaderToNodeHeaders(
headersInit: HeadersInit,
defaultNodeHeaders?: http.OutgoingHttpHeaders,
): http.OutgoingHttpHeaders;
export function webHeaderToNodeHeaders(
headersInit: HeadersInit | undefined,
): http.OutgoingHttpHeaders | undefined;
export function webHeaderToNodeHeaders(
headersInit: HeadersInit | undefined,
defaultNodeHeaders?: http.OutgoingHttpHeaders,
): http.OutgoingHttpHeaders | undefined {
if (headersInit === undefined) {
if (headersInit === undefined && defaultNodeHeaders === undefined) {
return undefined;
}
const o = Object.create(null) as http.OutgoingHttpHeaders;
const append = (key: string, value: string): void => {
key = key.toLowerCase();
const existing = o[key];
if (typeof existing == "string") {
o[key] = [existing, value];
} else if (Array.isArray(existing)) {
existing.push(value);
} else {
o[key] = value;
}
};
if (Array.isArray(headersInit)) {
for (const [key, value] of headersInit) {
append(key, value);
}
} else if ("forEach" in headersInit) {
if (typeof headersInit.forEach == "function") {
headersInit.forEach((value, key) => {
append(key, value);
});
if (defaultNodeHeaders !== undefined) {
for (const [key, value] of Object.entries(defaultNodeHeaders)) {
if (Array.isArray(value)) {
o[key] = value.concat();
} else if (value !== undefined) {
o[key] = value;
}
}
} else {
for (const [key, value] of Object.entries<string>(headersInit)) {
append(key, value);
}
if (headersInit !== undefined) {
if (Array.isArray(headersInit)) {
for (const [key, value] of headersInit) {
appendWebHeader(o, key, value);
}
} else if ("forEach" in headersInit) {
if (typeof headersInit.forEach == "function") {
headersInit.forEach((value, key) => {
appendWebHeader(o, key, value);
});
}
} else {
for (const [key, value] of Object.entries<string>(headersInit)) {
appendWebHeader(o, key, value);
}
}
}
return o;
}

function appendWebHeader(
o: http.OutgoingHttpHeaders,
key: string,
value: string,
) {
key = key.toLowerCase();
const existing = o[key];
if (Array.isArray(existing)) {
existing.push(value);
} else if (existing === undefined) {
o[key] = value;
} else {
o[key] = [existing.toString(), value];
}
}

0 comments on commit ed63cee

Please sign in to comment.