responses-session-id.test.ts 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. import { describe, expect, test } from "vitest";
  2. import { ProxyResponses } from "@/app/v1/_lib/proxy/responses";
  3. import { attachSessionIdToErrorResponse } from "@/app/v1/_lib/proxy/error-session-id";
  4. describe("ProxyResponses.attachSessionIdToErrorResponse", () => {
  5. test("adds x-cch-session-id and appends to error.message for JSON error responses", async () => {
  6. const response = ProxyResponses.buildError(400, "bad request");
  7. const decorated = await attachSessionIdToErrorResponse("s_123", response);
  8. expect(decorated.status).toBe(400);
  9. expect(decorated.headers.get("x-cch-session-id")).toBe("s_123");
  10. const body = await decorated.json();
  11. expect(body.error.message).toBe("bad request (cch_session_id: s_123)");
  12. });
  13. test("does nothing when sessionId is missing", async () => {
  14. const response = ProxyResponses.buildError(400, "bad request");
  15. const decorated = await attachSessionIdToErrorResponse(undefined, response);
  16. expect(decorated).toBe(response);
  17. });
  18. test("does nothing for non-error responses", async () => {
  19. const response = new Response(JSON.stringify({ ok: true }), {
  20. status: 200,
  21. headers: { "Content-Type": "application/json" },
  22. });
  23. const decorated = await attachSessionIdToErrorResponse("s_123", response);
  24. expect(decorated).toBe(response);
  25. });
  26. test("does not double-append when message already contains cch_session_id", async () => {
  27. const response = ProxyResponses.buildError(400, "bad request (cch_session_id: s_123)");
  28. const decorated = await attachSessionIdToErrorResponse("s_123", response);
  29. const body = await decorated.json();
  30. expect(body.error.message).toBe("bad request (cch_session_id: s_123)");
  31. });
  32. test("adds header for non-json error responses (body unchanged)", async () => {
  33. const response = new Response("oops", {
  34. status: 500,
  35. headers: { "Content-Type": "text/plain" },
  36. });
  37. const decorated = await attachSessionIdToErrorResponse("s_123", response);
  38. expect(decorated.status).toBe(500);
  39. expect(decorated.headers.get("x-cch-session-id")).toBe("s_123");
  40. expect(await decorated.text()).toBe("oops");
  41. });
  42. test("adds header for json without error.message (body unchanged)", async () => {
  43. const response = new Response(JSON.stringify({ foo: "bar" }), {
  44. status: 500,
  45. headers: { "Content-Type": "application/json" },
  46. });
  47. const decorated = await attachSessionIdToErrorResponse("s_123", response);
  48. expect(decorated.headers.get("x-cch-session-id")).toBe("s_123");
  49. expect(await decorated.json()).toEqual({ foo: "bar" });
  50. });
  51. test("adds header for SSE error responses (no body rewrite)", async () => {
  52. const response = new Response("data: hi\n\n", {
  53. status: 500,
  54. headers: { "Content-Type": "text/event-stream" },
  55. });
  56. const decorated = await attachSessionIdToErrorResponse("s_123", response);
  57. expect(decorated.headers.get("x-cch-session-id")).toBe("s_123");
  58. expect(await decorated.text()).toBe("data: hi\n\n");
  59. });
  60. });