Fixes: 1. media.ts: wrap placeholder generation in try-catch 2. toolbar.ts: check r.ok, display error message in popover
98 lines
3.6 KiB
TypeScript
98 lines
3.6 KiB
TypeScript
/**
|
|
* Tests for getTrustedProxyHeaders — resolves the list of trusted client-IP
|
|
* headers from config, falling back to the EMDASH_TRUSTED_PROXY_HEADERS env
|
|
* var, then to an empty array.
|
|
*
|
|
* The helper lets operators declare which headers they trust when running
|
|
* behind a reverse proxy. On Cloudflare the `cf` object is used instead and
|
|
* this list is usually empty.
|
|
*/
|
|
|
|
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
|
|
import {
|
|
_resetTrustedProxyHeadersCache,
|
|
getTrustedProxyHeaders,
|
|
} from "../../../src/auth/trusted-proxy.js";
|
|
|
|
describe("getTrustedProxyHeaders", () => {
|
|
const ORIGINAL_ENV = process.env.EMDASH_TRUSTED_PROXY_HEADERS;
|
|
|
|
beforeEach(() => {
|
|
_resetTrustedProxyHeadersCache();
|
|
});
|
|
|
|
afterEach(() => {
|
|
if (ORIGINAL_ENV === undefined) {
|
|
delete process.env.EMDASH_TRUSTED_PROXY_HEADERS;
|
|
} else {
|
|
process.env.EMDASH_TRUSTED_PROXY_HEADERS = ORIGINAL_ENV;
|
|
}
|
|
_resetTrustedProxyHeadersCache();
|
|
});
|
|
|
|
it("returns config value when set", () => {
|
|
expect(getTrustedProxyHeaders({ trustedProxyHeaders: ["x-real-ip"] })).toEqual(["x-real-ip"]);
|
|
});
|
|
|
|
it("prefers config over env", () => {
|
|
process.env.EMDASH_TRUSTED_PROXY_HEADERS = "fly-client-ip";
|
|
expect(getTrustedProxyHeaders({ trustedProxyHeaders: ["x-real-ip"] })).toEqual(["x-real-ip"]);
|
|
});
|
|
|
|
it("falls back to env when config is absent", () => {
|
|
process.env.EMDASH_TRUSTED_PROXY_HEADERS = "x-real-ip,fly-client-ip";
|
|
expect(getTrustedProxyHeaders(undefined)).toEqual(["x-real-ip", "fly-client-ip"]);
|
|
});
|
|
|
|
it("trims whitespace and drops empty entries from env", () => {
|
|
process.env.EMDASH_TRUSTED_PROXY_HEADERS = " x-real-ip , , fly-client-ip ";
|
|
expect(getTrustedProxyHeaders(undefined)).toEqual(["x-real-ip", "fly-client-ip"]);
|
|
});
|
|
|
|
it("lowercases header names for consistent matching", () => {
|
|
// Header lookups go through Headers.get() which is case-insensitive,
|
|
// so we normalise the list here to avoid double-normalising elsewhere.
|
|
expect(getTrustedProxyHeaders({ trustedProxyHeaders: ["X-Real-IP", "Fly-Client-IP"] })).toEqual(
|
|
["x-real-ip", "fly-client-ip"],
|
|
);
|
|
});
|
|
|
|
it("returns empty array when neither config nor env is set", () => {
|
|
delete process.env.EMDASH_TRUSTED_PROXY_HEADERS;
|
|
expect(getTrustedProxyHeaders(undefined)).toEqual([]);
|
|
});
|
|
|
|
it("returns empty array when config has empty list", () => {
|
|
process.env.EMDASH_TRUSTED_PROXY_HEADERS = "x-real-ip";
|
|
// An explicit empty array means "trust nothing" — do not fall through
|
|
// to the env. Operators use this to override an inherited env value.
|
|
expect(getTrustedProxyHeaders({ trustedProxyHeaders: [] })).toEqual([]);
|
|
});
|
|
|
|
// Header names must be valid RFC 7230 tokens; passing anything else into
|
|
// `Headers.get()` throws. Drop invalid entries silently rather than
|
|
// taking down every rate-limited endpoint with a 500.
|
|
it("drops invalid header names from config", () => {
|
|
expect(
|
|
getTrustedProxyHeaders({
|
|
trustedProxyHeaders: ["x-real-ip", "", "invalid name", "bad:colon", "ok-name"],
|
|
}),
|
|
).toEqual(["x-real-ip", "ok-name"]);
|
|
});
|
|
|
|
it("drops invalid header names from env", () => {
|
|
process.env.EMDASH_TRUSTED_PROXY_HEADERS = "x-real-ip, x y z , bad:one, ok-name";
|
|
expect(getTrustedProxyHeaders(undefined)).toEqual(["x-real-ip", "ok-name"]);
|
|
});
|
|
|
|
it("trims whitespace from config entries before matching", () => {
|
|
// Common typo: `"x-real-ip "` (trailing space). Previously the raw
|
|
// value was lowercased but not trimmed, so validation silently
|
|
// dropped it and per-IP bucketing was disabled.
|
|
expect(
|
|
getTrustedProxyHeaders({ trustedProxyHeaders: [" x-real-ip ", "fly-client-ip"] }),
|
|
).toEqual(["x-real-ip", "fly-client-ip"]);
|
|
});
|
|
});
|