Newer
Older
client_dwatch / lib / proxy / __tests__ / request-id.test.ts
/**
 * 相関IDの発行。★クライアント指定の値を信頼しないこと★を固定する。
 */
import { describe, expect, it } from "vitest";
import {
  issueRequestHeaders,
  REQUEST_ID_HEADER,
} from "@/lib/proxy/request-id";

describe("issueRequestHeaders()", () => {
  it("ヘッダ名は x-request-id(docs/logging-design.md で確定済み)", () => {
    expect(REQUEST_ID_HEADER).toBe("x-request-id");
  });

  it("相関IDを発行し、後段へ渡すヘッダに載せる", () => {
    const { requestId, headers } = issueRequestHeaders(new Headers());
    expect(requestId).toMatch(/^[0-9a-f-]{36}$/);
    expect(headers.get(REQUEST_ID_HEADER)).toBe(requestId);
  });

  it("★クライアントが送ってきた x-request-id は常に上書きする★", () => {
    const source = new Headers({ [REQUEST_ID_HEADER]: "attacker-supplied-id" });
    const { requestId, headers } = issueRequestHeaders(source);
    expect(requestId).not.toBe("attacker-supplied-id");
    expect(headers.get(REQUEST_ID_HEADER)).not.toBe("attacker-supplied-id");
    expect(headers.get(REQUEST_ID_HEADER)).toBe(requestId);
  });

  it("元の Headers を変更しない(複製して返す)", () => {
    const source = new Headers({ [REQUEST_ID_HEADER]: "original" });
    issueRequestHeaders(source);
    expect(source.get(REQUEST_ID_HEADER)).toBe("original");
  });

  it("他のヘッダは引き継ぐ(x-forwarded-for が後段から読めること)", () => {
    const source = new Headers({ "x-forwarded-for": "1.2.3.4, 203.0.113.10" });
    const { headers } = issueRequestHeaders(source);
    expect(headers.get("x-forwarded-for")).toBe("1.2.3.4, 203.0.113.10");
  });

  it("呼ぶたびに違うIDになる", () => {
    const a = issueRequestHeaders(new Headers()).requestId;
    const b = issueRequestHeaders(new Headers()).requestId;
    expect(a).not.toBe(b);
  });
});