url.test.ts 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. import { describe, expect, test, vi } from "vitest";
  2. vi.mock("@/lib/logger", () => ({
  3. logger: {
  4. debug: vi.fn(),
  5. error: vi.fn(),
  6. },
  7. }));
  8. import { buildProxyUrl } from "@/app/v1/_lib/url";
  9. describe("buildProxyUrl", () => {
  10. test("标准拼接:baseUrl 无路径时使用 requestPath + search", () => {
  11. const out = buildProxyUrl(
  12. "https://api.example.com",
  13. new URL("https://dummy.com/v1/messages?x=1")
  14. );
  15. expect(out).toBe("https://api.example.com/v1/messages?x=1");
  16. });
  17. test("避免重复拼接:baseUrl 已包含 /responses 时不追加 /v1/responses", () => {
  18. const out = buildProxyUrl(
  19. "https://example.com/openai/responses",
  20. new URL("https://dummy.com/v1/responses?x=1")
  21. );
  22. expect(out).toBe("https://example.com/openai/responses?x=1");
  23. });
  24. test("子路径不丢失:baseUrl=/v1/messages + request=/v1/messages/count_tokens", () => {
  25. const out = buildProxyUrl(
  26. "https://api.example.com/v1/messages",
  27. new URL("https://dummy.com/v1/messages/count_tokens")
  28. );
  29. expect(out).toBe("https://api.example.com/v1/messages/count_tokens");
  30. });
  31. test("带前缀路径的 baseUrl:/openai/messages + /v1/messages/count_tokens", () => {
  32. const out = buildProxyUrl(
  33. "https://example.com/openai/messages",
  34. new URL("https://dummy.com/v1/messages/count_tokens")
  35. );
  36. expect(out).toBe("https://example.com/openai/messages/count_tokens");
  37. });
  38. test("query 以 requestUrl 为准(覆盖 baseUrl 自带 query)", () => {
  39. const out = buildProxyUrl(
  40. "https://api.example.com/v1/messages?from=base",
  41. new URL("https://dummy.com/v1/messages?from=request")
  42. );
  43. expect(out).toBe("https://api.example.com/v1/messages?from=request");
  44. });
  45. test("baseUrl 以 /models 结尾时去除请求中的版本前缀", () => {
  46. const out = buildProxyUrl(
  47. "https://api.example.com/gemini/models",
  48. new URL("https://dummy.com/v1beta/models/gemini-1.5-pro:streamGenerateContent")
  49. );
  50. expect(out).toBe("https://api.example.com/gemini/models/gemini-1.5-pro:streamGenerateContent");
  51. });
  52. test("支持 v1internal 版本前缀", () => {
  53. const out = buildProxyUrl(
  54. "https://example.com/gemini/models",
  55. new URL("https://dummy.com/v1internal/models/gemini-2.5-flash:generateContent")
  56. );
  57. expect(out).toBe("https://example.com/gemini/models/gemini-2.5-flash:generateContent");
  58. });
  59. test("支持未来的版本前缀如 v2", () => {
  60. const out = buildProxyUrl(
  61. "https://example.com/api/models",
  62. new URL("https://dummy.com/v2/models/some-model:action")
  63. );
  64. expect(out).toBe("https://example.com/api/models/some-model:action");
  65. });
  66. });