Files
pangolin/server/lib/traefik/headersMiddleware.ts
T
Julian van der HorstandClaude Opus 5 6ad09adefa Merge upstream/dev into feature-response-headers
Resolve conflicts against upstream's refactors:

- server/db/sqlite/schema/schema.ts: adopt upstream's reindented
  sqliteTable(name, cols, indexes) form for sites/resources, re-applying
  the headers -> requestHeaders/responseHeaders split. Kept in sync with
  the Postgres schema.
- server/lib/traefik/headersMiddleware.ts: extend upstream's extracted
  buildCustomHeadersMiddleware helper to take requestHeaders and
  responseHeaders and emit both customRequestHeaders and
  customResponseHeaders.
- server/lib/traefik/getTraefikConfig.ts and
  server/private/lib/traefik/getTraefikConfig.ts: keep upstream's helper
  extraction and appendPathMatch refactor, dropping the superseded inline
  blocks.

Also carry the feature forward onto code that moved upstream:

- The resource settings UI moved from resources/proxy/[niceId]/proxy to
  resources/public/[niceId]/http, which dropped this branch's changes in
  the previous merge. Re-add the request/response header inputs there and
  rename the vestigial headers field on the tcp page.
- messages/da-DK.json is new upstream and still had the old customHeaders
  key; rename it in line with the other locales.

Per the contributing docs, versioned migrations are intentionally omitted
so maintainers can write them at release time.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-01 13:40:49 +02:00

79 lines
2.1 KiB
TypeScript

import logger from "@server/logger";
function parseHeaders(
headers: string,
label: string,
resourceId: number
): { name: string; value: string }[] {
try {
return JSON.parse(headers) as {
name: string;
value: string;
}[];
} catch (e) {
logger.warn(
`Failed to parse ${label} for resource ${resourceId}: ${e}`
);
return [];
}
}
/**
* Build the custom headers middleware definition for a resource's
* custom request/response headers + setHostHeader config. Returns null when
* there are no headers to set, so the caller can skip attaching the
* middleware.
*/
export function buildCustomHeadersMiddleware(
requestHeaders: string | null | undefined,
responseHeaders: string | null | undefined,
setHostHeader: string | null | undefined,
resourceId: number
): {
headers: {
customRequestHeaders?: { [key: string]: string };
customResponseHeaders?: { [key: string]: string };
};
} | null {
const requestHeadersObj: { [key: string]: string } = {};
const responseHeadersObj: { [key: string]: string } = {};
if (requestHeaders) {
parseHeaders(requestHeaders, "requestHeaders", resourceId).forEach(
(header) => {
requestHeadersObj[header.name] = header.value;
}
);
}
if (setHostHeader) {
requestHeadersObj["Host"] = setHostHeader;
}
if (responseHeaders) {
parseHeaders(responseHeaders, "responseHeaders", resourceId).forEach(
(header) => {
responseHeadersObj[header.name] = header.value;
}
);
}
const hasRequestHeaders = Object.keys(requestHeadersObj).length > 0;
const hasResponseHeaders = Object.keys(responseHeadersObj).length > 0;
if (!hasRequestHeaders && !hasResponseHeaders) {
return null;
}
return {
headers: {
...(hasRequestHeaders && {
customRequestHeaders: requestHeadersObj
}),
...(hasResponseHeaders && {
customResponseHeaders: responseHeadersObj
})
}
};
}