Adapt per review

This commit is contained in:
Reinier Criel 2026-04-02 08:56:20 -07:00
parent 06ef0c3990
commit 0aabba668e
3 changed files with 75 additions and 41 deletions

View file

@ -16,9 +16,42 @@ export function getHeaderValueAsString(headers, headerName) {
return header; return header;
} }
/**
* Returns a copy of headers without the provided header names, matched
* either exactly or case-insensitively.
*
* @param {NodeJS.Dict<string | string[]> | undefined} headers
* @param {string[]} headerNames
* @param {{ caseInsensitive?: boolean }} [options]
* @returns {NodeJS.Dict<string | string[]> | undefined}
*/
export function omitHeaders(headers, headerNames, options = {}) {
if (!headers) {
return headers;
}
const omittedHeaderNames = new Set(
options.caseInsensitive
? headerNames.map((name) => name.toLowerCase())
: headerNames
);
/** @type {NodeJS.Dict<string | string[]>} */
const filteredHeaders = {};
for (const [headerName, value] of Object.entries(headers)) {
const comparableHeaderName = options.caseInsensitive
? headerName.toLowerCase()
: headerName;
if (!omittedHeaderNames.has(comparableHeaderName)) {
filteredHeaders[headerName] = value;
}
}
return filteredHeaders;
}
/** /**
* Remove headers that become stale when the response body is modified. * Remove headers that become stale when the response body is modified.
* Mutates the provided headers object in place.
* *
* @param {NodeJS.Dict<string | string[]> | undefined} headers * @param {NodeJS.Dict<string | string[]> | undefined} headers
* @returns {void} * @returns {void}
@ -28,8 +61,20 @@ export function clearCachingHeaders(headers) {
return; return;
} }
delete headers["etag"]; const filteredHeaders = omitHeaders(headers, [
delete headers["last-modified"]; "etag",
delete headers["cache-control"]; "last-modified",
delete headers["content-length"]; "cache-control",
"content-length",
]);
if (!filteredHeaders) {
return;
}
for (const key of Object.keys(headers)) {
delete headers[key];
}
Object.assign(headers, filteredHeaders);
} }

View file

@ -37,21 +37,27 @@ export function getAvailableVersionsFromJson(json, metadataUrl) {
return Object.keys(json.releases); return Object.keys(json.releases);
} }
if (Array.isArray(json.files)) { if (!Array.isArray(json.files)) {
return [ return [];
...new Set(
json.files
.map((/** @type {any} */ file) =>
getPackageVersionFromMetadataFile(file, metadataUrl)
)
.filter((/** @type {string | undefined} */ version) =>
typeof version === "string"
)
),
];
} }
return []; return [
...new Set(
json.files
.map((/** @type {any} */ file) =>
getPackageVersionFromMetadataFile(file, metadataUrl)
)
.filter(isDefinedString)
),
];
}
/**
* @param {string | undefined} value
* @returns {value is string}
*/
function isDefinedString(value) {
return typeof value === "string";
} }
/** /**

View file

@ -3,6 +3,7 @@ import { generateCertForHost } from "./certUtils.js";
import { HttpsProxyAgent } from "https-proxy-agent"; import { HttpsProxyAgent } from "https-proxy-agent";
import { ui } from "../environment/userInteraction.js"; import { ui } from "../environment/userInteraction.js";
import { gunzipSync } from "zlib"; import { gunzipSync } from "zlib";
import { omitHeaders } from "./http-utils.js";
/** /**
* @typedef {import("./interceptors/interceptorBuilder.js").Interceptor} Interceptor * @typedef {import("./interceptors/interceptorBuilder.js").Interceptor} Interceptor
@ -107,28 +108,6 @@ function getRequestPathAndQuery(url) {
return url; return url;
} }
/**
* @param {NodeJS.Dict<string | string[]>} headers
* @returns {NodeJS.Dict<string | string[]>}
*/
function normalizeRewrittenResponseHeaders(headers) {
/** @type {NodeJS.Dict<string | string[]>} */
const normalizedHeaders = { ...headers };
for (const headerName of Object.keys(headers)) {
const lowerHeaderName = headerName.toLowerCase();
if (
lowerHeaderName === "content-length" ||
lowerHeaderName === "transfer-encoding" ||
lowerHeaderName === "content-encoding"
) {
delete normalizedHeaders[headerName];
}
}
return normalizedHeaders;
}
/** /**
* @param {import("http").IncomingMessage} req * @param {import("http").IncomingMessage} req
* @param {string} hostname * @param {string} hostname
@ -240,7 +219,11 @@ function createProxyRequest(hostname, port, req, res, requestHandler) {
// For rewritten responses, send the final body uncompressed. // For rewritten responses, send the final body uncompressed.
// This avoids mismatches between upstream compression metadata and the // This avoids mismatches between upstream compression metadata and the
// rewritten payload on the wire. // rewritten payload on the wire.
const rewrittenHeaders = normalizeRewrittenResponseHeaders(headers); const rewrittenHeaders = omitHeaders(
headers,
["content-length", "transfer-encoding", "content-encoding"],
{ caseInsensitive: true }
) || {};
rewrittenHeaders["content-length"] = String(buffer.byteLength); rewrittenHeaders["content-length"] = String(buffer.byteLength);
res.writeHead(statusCode, rewrittenHeaders); res.writeHead(statusCode, rewrittenHeaders);
res.end(buffer); res.end(buffer);