1// Alchemy modifications are licensed under Apache-2.0.
2// This file includes third-party code; see /THIRD_PARTY_LICENSES.md.
3import { test } from "vitest";
4import { parseHeaders } from "../configuration/parseHeaders.ts";
5
6test("parseHeaders should handle a single rule", ({ expect }) => {
7 const input = `/a
8 Name: Value`;
9 const result = parseHeaders(input);
10 expect(result).toEqual({
11 rules: [{ path: "/a", headers: { name: "Value" }, unsetHeaders: [] }],
12 invalid: [],
13 });
14});
15
16test("parseHeaders should handle headers with exclamation marks", ({
17 expect,
18}) => {
19 const input = `/a
20 !Name: Value`;
21 const result = parseHeaders(input);
22 expect(result).toEqual({
23 rules: [{ path: "/a", headers: { "!name": "Value" }, unsetHeaders: [] }],
24 invalid: [],
25 });
26});
27
28test("parseHeaders should ignore blank lines", ({ expect }) => {
29 const input = `
30/a
31
32Name: Value
33
34`;
35 const result = parseHeaders(input);
36 expect(result).toEqual({
37 rules: [{ path: "/a", headers: { name: "Value" }, unsetHeaders: [] }],
38 invalid: [],
39 });
40});
41
42test("parseHeaders should trim whitespace", ({ expect }) => {
43 const input = `
44 /a
45 Name : Value
46`;
47 const result = parseHeaders(input);
48 expect(result).toEqual({
49 rules: [{ path: "/a", headers: { name: "Value" }, unsetHeaders: [] }],
50 invalid: [],
51 });
52});
53
54test("parseHeaders should ignore comments", ({ expect }) => {
55 const input = `
56 # This is a comment
57 /a
58 # And one here too.
59 Name: Value
60`;
61 const result = parseHeaders(input);
62 expect(result).toEqual({
63 rules: [{ path: "/a", headers: { name: "Value" }, unsetHeaders: [] }],
64 invalid: [],
65 });
66});
67
68test("parseHeaders should combine headers together", ({ expect }) => {
69 const input = `
70 /a
71 Set-Cookie: test=cookie; expires=never
72 Set-Cookie: another=cookie; magic!
73
74 /b
75 A: ABBA
76 B: BABA
77`;
78 const result = parseHeaders(input);
79 expect(result).toEqual({
80 rules: [
81 {
82 path: "/a",
83 headers: {
84 "set-cookie": "test=cookie; expires=never, another=cookie; magic!",
85 },
86 unsetHeaders: [],
87 },
88 {
89 path: "/b",
90 headers: { a: "ABBA", b: "BABA" },
91 unsetHeaders: [],
92 },
93 ],
94 invalid: [],
95 });
96});
97
98test("parseHeaders should support setting hosts", ({ expect }) => {
99 const input = `
100 https://example.com
101 a: a
102 https://example.com/
103 b: b
104 https://example.com/blog
105 c: c
106 /blog
107 d:d
108 https://:subdomain.example.*/path
109 e:e
110`;
111 const result = parseHeaders(input);
112 expect(result).toEqual({
113 rules: [
114 { path: "https://example.com/", headers: { a: "a" }, unsetHeaders: [] },
115 { path: "https://example.com/", headers: { b: "b" }, unsetHeaders: [] },
116 {
117 path: "https://example.com/blog",
118 headers: { c: "c" },
119 unsetHeaders: [],
120 },
121 { path: "/blog", headers: { d: "d" }, unsetHeaders: [] },
122 {
123 path: "https://:subdomain.example.*/path",
124 headers: { e: "e" },
125 unsetHeaders: [],
126 },
127 ],
128 invalid: [],
129 });
130});
131
132test("parseHeaders should add unset headers", ({ expect }) => {
133 const input = `/a
134 Name: Value
135 ! Place`;
136 const result = parseHeaders(input);
137 expect(result).toEqual({
138 rules: [
139 { path: "/a", headers: { name: "Value" }, unsetHeaders: ["Place"] },
140 ],
141 invalid: [],
142 });
143});
144
145test("parseHeaders should support custom limits", ({ expect }) => {
146 const aaa = Array(1001).fill("a").join("");
147 const bbb = Array(1001).fill("b").join("");
148 const huge_line = `${aaa}: ${bbb}`;
149 let input = `
150 # Valid entry
151 /a
152 Name: Value
153 # Jumbo comment line OK, ignored as normal
154 ${Array(1001).fill("#").join("")}
155 # Huge path names rejected
156 /b
157 Name: Value
158 ${huge_line}
159 `;
160 let result = parseHeaders(input, { maxLineLength: 3000 });
161 expect(result).toEqual({
162 rules: [
163 { path: "/a", headers: { name: "Value" }, unsetHeaders: [] },
164 { path: "/b", headers: { name: "Value", [aaa]: bbb }, unsetHeaders: [] },
165 ],
166 invalid: [],
167 });
168
169 input = `
170 # COMMENTS DON'T COUNT TOWARDS TOTAL VALID RULES
171 ${Array(150)
172 .fill(undefined)
173 .map((_, i) => `/a/${i}\nx-index: ${i}`)
174 .join("\n")}
175 # BUT DO GET COUNTED AS TOTAL LINES SKIPPED
176 `;
177 result = parseHeaders(input, { maxRules: 200 });
178 expect(result.rules.length).toBe(150);
179 expect(result.invalid.length).toBe(0);
180});