request-filter-engine.test.ts 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. import { describe, expect, test } from "vitest";
  2. import { requestFilterEngine } from "@/lib/request-filter-engine";
  3. import type { RequestFilter } from "@/repository/request-filters";
  4. function createSession() {
  5. return {
  6. headers: new Headers({
  7. "user-agent": "UA",
  8. "x-remove": "foo",
  9. }),
  10. request: {
  11. message: {
  12. nested: { secret: "abc" },
  13. text: "hello secret",
  14. },
  15. log: "",
  16. model: "claude-3",
  17. },
  18. } as unknown as Parameters<typeof requestFilterEngine.apply>[0];
  19. }
  20. describe("请求过滤引擎", () => {
  21. test("应该正确应用 Header 删除/设置和 Body 变更", async () => {
  22. const filters: RequestFilter[] = [
  23. {
  24. id: 1,
  25. name: "remove-header",
  26. description: null,
  27. scope: "header",
  28. action: "remove",
  29. matchType: null,
  30. target: "x-remove",
  31. replacement: null,
  32. priority: 0,
  33. isEnabled: true,
  34. createdAt: new Date(),
  35. updatedAt: new Date(),
  36. },
  37. {
  38. id: 2,
  39. name: "set-ua",
  40. description: null,
  41. scope: "header",
  42. action: "set",
  43. matchType: null,
  44. target: "user-agent",
  45. replacement: "custom-UA",
  46. priority: 1,
  47. isEnabled: true,
  48. createdAt: new Date(),
  49. updatedAt: new Date(),
  50. },
  51. {
  52. id: 3,
  53. name: "json-path",
  54. description: null,
  55. scope: "body",
  56. action: "json_path",
  57. matchType: null,
  58. target: "nested.secret",
  59. replacement: "***",
  60. priority: 2,
  61. isEnabled: true,
  62. createdAt: new Date(),
  63. updatedAt: new Date(),
  64. },
  65. {
  66. id: 4,
  67. name: "text-replace",
  68. description: null,
  69. scope: "body",
  70. action: "text_replace",
  71. matchType: "contains",
  72. target: "secret",
  73. replacement: "[redacted]",
  74. priority: 3,
  75. isEnabled: true,
  76. createdAt: new Date(),
  77. updatedAt: new Date(),
  78. },
  79. ];
  80. requestFilterEngine.setFiltersForTest(filters);
  81. const session = createSession();
  82. await requestFilterEngine.apply(session);
  83. expect(session.headers.has("x-remove")).toBe(false);
  84. expect(session.headers.get("user-agent")).toBe("custom-UA");
  85. expect((session.request.message as any).nested.secret).toBe("***");
  86. expect((session.request.message as any).text).toContain("[redacted]");
  87. });
  88. test("应该忽略不安全的正则表达式(不抛出错误)", async () => {
  89. requestFilterEngine.setFiltersForTest([
  90. {
  91. id: 1,
  92. name: "unsafe",
  93. description: null,
  94. scope: "body",
  95. action: "text_replace",
  96. matchType: "regex",
  97. target: "(a+)+",
  98. replacement: "x",
  99. priority: 0,
  100. isEnabled: true,
  101. createdAt: new Date(),
  102. updatedAt: new Date(),
  103. },
  104. ]);
  105. const session = createSession();
  106. await expect(requestFilterEngine.apply(session)).resolves.toBeUndefined();
  107. // body remains unchanged because regex skipped
  108. expect((session.request.message as any).text).toBe("hello secret");
  109. });
  110. });