1use crate::cookie::CookieJar;
7use bytes::{Bytes, BytesMut};
8use http::HeaderMap;
9use std::sync::{Arc, OnceLock};
10
11pub fn chrome_142_headers() -> Vec<(&'static str, &'static str)> {
13 vec![
14 (
15 "User-Agent",
16 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36",
17 ),
18 (
19 "Accept",
20 "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
21 ),
22 ("Accept-Language", "en-US,en;q=0.9"),
23 ("Accept-Encoding", "gzip, deflate, br, zstd"),
24 ("Sec-Fetch-Dest", "document"),
25 ("Sec-Fetch-Mode", "navigate"),
26 ("Sec-Fetch-Site", "none"),
27 ("Sec-Fetch-User", "?1"),
28 (
29 "Sec-Ch-Ua",
30 r#""Chromium";v="142", "Google Chrome";v="142", "Not_A Brand";v="99""#,
31 ),
32 ("Sec-Ch-Ua-Mobile", "?0"),
33 ("Sec-Ch-Ua-Platform", r#""macOS""#),
34 ("Sec-Ch-Ua-Arch", r#""arm64""#),
35 ("Sec-Ch-Ua-Bitness", r#""64""#),
36 (
37 "Sec-Ch-Ua-Full-Version-List",
38 r#""Chromium";v="142.0.7444.176", "Google Chrome";v="142.0.7444.176", "Not_A Brand";v="99.0.0.0""#,
39 ),
40 ("Sec-Ch-Ua-Model", r#""""#),
41 ("Sec-Ch-Ua-Platform-Version", r#""15.5.0""#),
42 ("Sec-Ch-Ua-Wow64", "?0"),
43 ("Upgrade-Insecure-Requests", "1"),
44 ("Connection", "keep-alive"),
45 ]
46}
47
48pub fn chrome_142_ajax_headers() -> Vec<(&'static str, &'static str)> {
52 vec![
53 (
54 "User-Agent",
55 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36",
56 ),
57 ("Accept", "application/json, text/plain, */*"),
58 ("Accept-Language", "en-US,en;q=0.9"),
59 ("Accept-Encoding", "gzip, deflate, br, zstd"),
60 ("Content-Type", "application/json"),
61 ("Sec-Fetch-Dest", "empty"),
62 ("Sec-Fetch-Mode", "cors"),
63 ("Sec-Fetch-Site", "same-origin"),
64 (
65 "Sec-Ch-Ua",
66 r#""Chromium";v="142", "Google Chrome";v="142", "Not_A Brand";v="99""#,
67 ),
68 ("Sec-Ch-Ua-Mobile", "?0"),
69 ("Sec-Ch-Ua-Platform", r#""macOS""#),
70 ("Connection", "keep-alive"),
71 ]
72}
73
74pub fn chrome_142_form_headers() -> Vec<(&'static str, &'static str)> {
76 vec![
77 (
78 "User-Agent",
79 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36",
80 ),
81 (
82 "Accept",
83 "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
84 ),
85 ("Accept-Language", "en-US,en;q=0.9"),
86 ("Accept-Encoding", "gzip, deflate, br, zstd"),
87 ("Content-Type", "application/x-www-form-urlencoded"),
88 ("Sec-Fetch-Dest", "document"),
89 ("Sec-Fetch-Mode", "navigate"),
90 ("Sec-Fetch-Site", "same-origin"),
91 (
92 "Sec-Ch-Ua",
93 r#""Chromium";v="142", "Google Chrome";v="142", "Not_A Brand";v="99""#,
94 ),
95 ("Sec-Ch-Ua-Mobile", "?0"),
96 ("Sec-Ch-Ua-Platform", r#""macOS""#),
97 ("Sec-Ch-Ua-Arch", r#""arm64""#),
98 ("Sec-Ch-Ua-Bitness", r#""64""#),
99 (
100 "Sec-Ch-Ua-Full-Version-List",
101 r#""Chromium";v="142.0.7444.176", "Google Chrome";v="142.0.7444.176", "Not_A Brand";v="99.0.0.0""#,
102 ),
103 ("Sec-Ch-Ua-Model", r#""""#),
104 ("Sec-Ch-Ua-Platform-Version", r#""15.5.0""#),
105 ("Sec-Ch-Ua-Wow64", "?0"),
106 ("Upgrade-Insecure-Requests", "1"),
107 ("Connection", "keep-alive"),
108 ]
109}
110
111pub fn chrome_143_headers() -> Vec<(&'static str, &'static str)> {
113 vec![
114 (
115 "User-Agent",
116 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36",
117 ),
118 (
119 "Accept",
120 "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
121 ),
122 ("Accept-Language", "en-US,en;q=0.9"),
123 ("Accept-Encoding", "gzip, deflate, br, zstd"),
124 ("Sec-Fetch-Dest", "document"),
125 ("Sec-Fetch-Mode", "navigate"),
126 ("Sec-Fetch-Site", "none"),
127 ("Sec-Fetch-User", "?1"),
128 (
129 "Sec-Ch-Ua",
130 r#""Google Chrome";v="143", "Chromium";v="143", "Not A(Brand";v="24""#,
131 ),
132 ("Sec-Ch-Ua-Mobile", "?0"),
133 ("Sec-Ch-Ua-Platform", r#""macOS""#),
134 ("Sec-Ch-Ua-Arch", r#""arm64""#),
135 ("Sec-Ch-Ua-Bitness", r#""64""#),
136 (
137 "Sec-Ch-Ua-Full-Version-List",
138 r#""Google Chrome";v="143.0.7499.193", "Chromium";v="143.0.7499.193", "Not A(Brand";v="24.0.0.0""#,
139 ),
140 ("Sec-Ch-Ua-Model", r#""""#),
141 ("Sec-Ch-Ua-Platform-Version", r#""15.5.0""#),
142 ("Sec-Ch-Ua-Wow64", "?0"),
143 ("Upgrade-Insecure-Requests", "1"),
144 ("Connection", "keep-alive"),
145 ]
146}
147
148pub fn chrome_143_ajax_headers() -> Vec<(&'static str, &'static str)> {
150 vec![
151 (
152 "User-Agent",
153 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36",
154 ),
155 ("Accept", "application/json, text/plain, */*"),
156 ("Accept-Language", "en-US,en;q=0.9"),
157 ("Accept-Encoding", "gzip, deflate, br, zstd"),
158 ("Content-Type", "application/json"),
159 ("Sec-Fetch-Dest", "empty"),
160 ("Sec-Fetch-Mode", "cors"),
161 ("Sec-Fetch-Site", "same-origin"),
162 (
163 "Sec-Ch-Ua",
164 r#""Google Chrome";v="143", "Chromium";v="143", "Not A(Brand";v="24""#,
165 ),
166 ("Sec-Ch-Ua-Mobile", "?0"),
167 ("Sec-Ch-Ua-Platform", r#""macOS""#),
168 ("Connection", "keep-alive"),
169 ]
170}
171
172pub fn chrome_143_form_headers() -> Vec<(&'static str, &'static str)> {
174 vec![
175 (
176 "User-Agent",
177 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36",
178 ),
179 (
180 "Accept",
181 "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
182 ),
183 ("Accept-Language", "en-US,en;q=0.9"),
184 ("Accept-Encoding", "gzip, deflate, br, zstd"),
185 ("Content-Type", "application/x-www-form-urlencoded"),
186 ("Sec-Fetch-Dest", "document"),
187 ("Sec-Fetch-Mode", "navigate"),
188 ("Sec-Fetch-Site", "same-origin"),
189 (
190 "Sec-Ch-Ua",
191 r#""Google Chrome";v="143", "Chromium";v="143", "Not A(Brand";v="24""#,
192 ),
193 ("Sec-Ch-Ua-Mobile", "?0"),
194 ("Sec-Ch-Ua-Platform", r#""macOS""#),
195 ("Sec-Ch-Ua-Arch", r#""arm64""#),
196 ("Sec-Ch-Ua-Bitness", r#""64""#),
197 (
198 "Sec-Ch-Ua-Full-Version-List",
199 r#""Google Chrome";v="143.0.7499.193", "Chromium";v="143.0.7499.193", "Not A(Brand";v="24.0.0.0""#,
200 ),
201 ("Sec-Ch-Ua-Model", r#""""#),
202 ("Sec-Ch-Ua-Platform-Version", r#""15.5.0""#),
203 ("Sec-Ch-Ua-Wow64", "?0"),
204 ("Upgrade-Insecure-Requests", "1"),
205 ("Connection", "keep-alive"),
206 ]
207}
208
209pub fn chrome_144_headers() -> Vec<(&'static str, &'static str)> {
211 vec![
212 (
213 "User-Agent",
214 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36",
215 ),
216 (
217 "Accept",
218 "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
219 ),
220 ("Accept-Language", "en-US,en;q=0.9"),
221 ("Accept-Encoding", "gzip, deflate, br, zstd"),
222 ("Sec-Fetch-Dest", "document"),
223 ("Sec-Fetch-Mode", "navigate"),
224 ("Sec-Fetch-Site", "none"),
225 ("Sec-Fetch-User", "?1"),
226 (
227 "Sec-Ch-Ua",
228 r#""Not(A:Brand";v="8", "Chromium";v="144", "Google Chrome";v="144""#,
229 ),
230 ("Sec-Ch-Ua-Mobile", "?0"),
231 ("Sec-Ch-Ua-Platform", r#""macOS""#),
232 ("Sec-Ch-Ua-Arch", r#""arm64""#),
233 ("Sec-Ch-Ua-Bitness", r#""64""#),
234 (
235 "Sec-Ch-Ua-Full-Version-List",
236 r#""Not(A:Brand";v="8.0.0.0", "Chromium";v="144.0.7559.133", "Google Chrome";v="144.0.7559.133""#,
237 ),
238 ("Sec-Ch-Ua-Model", r#""""#),
239 ("Sec-Ch-Ua-Platform-Version", r#""15.5.0""#),
240 ("Sec-Ch-Ua-Wow64", "?0"),
241 ("Upgrade-Insecure-Requests", "1"),
242 ("Connection", "keep-alive"),
243 ]
244}
245
246pub fn chrome_144_ajax_headers() -> Vec<(&'static str, &'static str)> {
248 vec![
249 (
250 "User-Agent",
251 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36",
252 ),
253 ("Accept", "application/json, text/plain, */*"),
254 ("Accept-Language", "en-US,en;q=0.9"),
255 ("Accept-Encoding", "gzip, deflate, br, zstd"),
256 ("Content-Type", "application/json"),
257 ("Sec-Fetch-Dest", "empty"),
258 ("Sec-Fetch-Mode", "cors"),
259 ("Sec-Fetch-Site", "same-origin"),
260 (
261 "Sec-Ch-Ua",
262 r#""Not(A:Brand";v="8", "Chromium";v="144", "Google Chrome";v="144""#,
263 ),
264 ("Sec-Ch-Ua-Mobile", "?0"),
265 ("Sec-Ch-Ua-Platform", r#""macOS""#),
266 ("Connection", "keep-alive"),
267 ]
268}
269
270pub fn chrome_144_form_headers() -> Vec<(&'static str, &'static str)> {
272 vec![
273 (
274 "User-Agent",
275 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36",
276 ),
277 (
278 "Accept",
279 "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
280 ),
281 ("Accept-Language", "en-US,en;q=0.9"),
282 ("Accept-Encoding", "gzip, deflate, br, zstd"),
283 ("Content-Type", "application/x-www-form-urlencoded"),
284 ("Sec-Fetch-Dest", "document"),
285 ("Sec-Fetch-Mode", "navigate"),
286 ("Sec-Fetch-Site", "same-origin"),
287 (
288 "Sec-Ch-Ua",
289 r#""Not(A:Brand";v="8", "Chromium";v="144", "Google Chrome";v="144""#,
290 ),
291 ("Sec-Ch-Ua-Mobile", "?0"),
292 ("Sec-Ch-Ua-Platform", r#""macOS""#),
293 ("Sec-Ch-Ua-Arch", r#""arm64""#),
294 ("Sec-Ch-Ua-Bitness", r#""64""#),
295 (
296 "Sec-Ch-Ua-Full-Version-List",
297 r#""Not(A:Brand";v="8.0.0.0", "Chromium";v="144.0.7559.133", "Google Chrome";v="144.0.7559.133""#,
298 ),
299 ("Sec-Ch-Ua-Model", r#""""#),
300 ("Sec-Ch-Ua-Platform-Version", r#""15.5.0""#),
301 ("Sec-Ch-Ua-Wow64", "?0"),
302 ("Upgrade-Insecure-Requests", "1"),
303 ("Connection", "keep-alive"),
304 ]
305}
306
307pub fn chrome_145_headers() -> Vec<(&'static str, &'static str)> {
309 vec![
310 (
311 "User-Agent",
312 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36",
313 ),
314 (
315 "Accept",
316 "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
317 ),
318 ("Accept-Language", "en-US,en;q=0.9"),
319 ("Accept-Encoding", "gzip, deflate, br, zstd"),
320 ("Sec-Fetch-Dest", "document"),
321 ("Sec-Fetch-Mode", "navigate"),
322 ("Sec-Fetch-Site", "none"),
323 ("Sec-Fetch-User", "?1"),
324 (
325 "Sec-Ch-Ua",
326 r#""Not:A-Brand";v="99", "Google Chrome";v="145", "Chromium";v="145""#,
327 ),
328 ("Sec-Ch-Ua-Mobile", "?0"),
329 ("Sec-Ch-Ua-Platform", r#""macOS""#),
330 ("Sec-Ch-Ua-Arch", r#""arm64""#),
331 ("Sec-Ch-Ua-Bitness", r#""64""#),
332 (
333 "Sec-Ch-Ua-Full-Version-List",
334 r#""Not:A-Brand";v="99.0.0.0", "Google Chrome";v="145.0.7632.117", "Chromium";v="145.0.7632.117""#,
335 ),
336 ("Sec-Ch-Ua-Model", r#""""#),
337 ("Sec-Ch-Ua-Platform-Version", r#""15.5.0""#),
338 ("Sec-Ch-Ua-Wow64", "?0"),
339 ("Upgrade-Insecure-Requests", "1"),
340 ("Connection", "keep-alive"),
341 ]
342}
343
344pub fn chrome_145_ajax_headers() -> Vec<(&'static str, &'static str)> {
346 vec![
347 (
348 "User-Agent",
349 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36",
350 ),
351 ("Accept", "application/json, text/plain, */*"),
352 ("Accept-Language", "en-US,en;q=0.9"),
353 ("Accept-Encoding", "gzip, deflate, br, zstd"),
354 ("Content-Type", "application/json"),
355 ("Sec-Fetch-Dest", "empty"),
356 ("Sec-Fetch-Mode", "cors"),
357 ("Sec-Fetch-Site", "same-origin"),
358 (
359 "Sec-Ch-Ua",
360 r#""Not:A-Brand";v="99", "Google Chrome";v="145", "Chromium";v="145""#,
361 ),
362 ("Sec-Ch-Ua-Mobile", "?0"),
363 ("Sec-Ch-Ua-Platform", r#""macOS""#),
364 ("Connection", "keep-alive"),
365 ]
366}
367
368pub fn chrome_145_form_headers() -> Vec<(&'static str, &'static str)> {
370 vec![
371 (
372 "User-Agent",
373 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36",
374 ),
375 (
376 "Accept",
377 "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
378 ),
379 ("Accept-Language", "en-US,en;q=0.9"),
380 ("Accept-Encoding", "gzip, deflate, br, zstd"),
381 ("Content-Type", "application/x-www-form-urlencoded"),
382 ("Sec-Fetch-Dest", "document"),
383 ("Sec-Fetch-Mode", "navigate"),
384 ("Sec-Fetch-Site", "same-origin"),
385 (
386 "Sec-Ch-Ua",
387 r#""Not:A-Brand";v="99", "Google Chrome";v="145", "Chromium";v="145""#,
388 ),
389 ("Sec-Ch-Ua-Mobile", "?0"),
390 ("Sec-Ch-Ua-Platform", r#""macOS""#),
391 ("Sec-Ch-Ua-Arch", r#""arm64""#),
392 ("Sec-Ch-Ua-Bitness", r#""64""#),
393 (
394 "Sec-Ch-Ua-Full-Version-List",
395 r#""Not:A-Brand";v="99.0.0.0", "Google Chrome";v="145.0.7632.117", "Chromium";v="145.0.7632.117""#,
396 ),
397 ("Sec-Ch-Ua-Model", r#""""#),
398 ("Sec-Ch-Ua-Platform-Version", r#""15.5.0""#),
399 ("Sec-Ch-Ua-Wow64", "?0"),
400 ("Upgrade-Insecure-Requests", "1"),
401 ("Connection", "keep-alive"),
402 ]
403}
404
405pub fn chrome_146_headers() -> Vec<(&'static str, &'static str)> {
407 vec![
408 (
409 "User-Agent",
410 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36",
411 ),
412 (
413 "Accept",
414 "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
415 ),
416 ("Accept-Language", "en-US,en;q=0.9"),
417 ("Accept-Encoding", "gzip, deflate, br, zstd"),
418 ("Sec-Fetch-Dest", "document"),
419 ("Sec-Fetch-Mode", "navigate"),
420 ("Sec-Fetch-Site", "none"),
421 ("Sec-Fetch-User", "?1"),
422 (
423 "Sec-Ch-Ua",
424 r#""Chromium";v="146", "Not-A.Brand";v="24", "Google Chrome";v="146""#,
425 ),
426 ("Sec-Ch-Ua-Mobile", "?0"),
427 ("Sec-Ch-Ua-Platform", r#""macOS""#),
428 ("Sec-Ch-Ua-Arch", r#""arm64""#),
429 ("Sec-Ch-Ua-Bitness", r#""64""#),
430 (
431 "Sec-Ch-Ua-Full-Version-List",
432 r#""Chromium";v="146.0.7680.165", "Not-A.Brand";v="24.0.0.0", "Google Chrome";v="146.0.7680.165""#,
433 ),
434 ("Sec-Ch-Ua-Model", r#""""#),
435 ("Sec-Ch-Ua-Platform-Version", r#""15.5.0""#),
436 ("Sec-Ch-Ua-Wow64", "?0"),
437 ("Upgrade-Insecure-Requests", "1"),
438 ("Connection", "keep-alive"),
439 ]
440}
441
442pub fn chrome_146_ajax_headers() -> Vec<(&'static str, &'static str)> {
444 vec![
445 (
446 "User-Agent",
447 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36",
448 ),
449 ("Accept", "application/json, text/plain, */*"),
450 ("Accept-Language", "en-US,en;q=0.9"),
451 ("Accept-Encoding", "gzip, deflate, br, zstd"),
452 ("Content-Type", "application/json"),
453 ("Sec-Fetch-Dest", "empty"),
454 ("Sec-Fetch-Mode", "cors"),
455 ("Sec-Fetch-Site", "same-origin"),
456 (
457 "Sec-Ch-Ua",
458 r#""Chromium";v="146", "Not-A.Brand";v="24", "Google Chrome";v="146""#,
459 ),
460 ("Sec-Ch-Ua-Mobile", "?0"),
461 ("Sec-Ch-Ua-Platform", r#""macOS""#),
462 ("Connection", "keep-alive"),
463 ]
464}
465
466pub fn chrome_146_form_headers() -> Vec<(&'static str, &'static str)> {
468 vec![
469 (
470 "User-Agent",
471 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36",
472 ),
473 (
474 "Accept",
475 "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
476 ),
477 ("Accept-Language", "en-US,en;q=0.9"),
478 ("Accept-Encoding", "gzip, deflate, br, zstd"),
479 ("Content-Type", "application/x-www-form-urlencoded"),
480 ("Sec-Fetch-Dest", "document"),
481 ("Sec-Fetch-Mode", "navigate"),
482 ("Sec-Fetch-Site", "same-origin"),
483 (
484 "Sec-Ch-Ua",
485 r#""Chromium";v="146", "Not-A.Brand";v="24", "Google Chrome";v="146""#,
486 ),
487 ("Sec-Ch-Ua-Mobile", "?0"),
488 ("Sec-Ch-Ua-Platform", r#""macOS""#),
489 ("Sec-Ch-Ua-Arch", r#""arm64""#),
490 ("Sec-Ch-Ua-Bitness", r#""64""#),
491 (
492 "Sec-Ch-Ua-Full-Version-List",
493 r#""Chromium";v="146.0.7680.165", "Not-A.Brand";v="24.0.0.0", "Google Chrome";v="146.0.7680.165""#,
494 ),
495 ("Sec-Ch-Ua-Model", r#""""#),
496 ("Sec-Ch-Ua-Platform-Version", r#""15.5.0""#),
497 ("Sec-Ch-Ua-Wow64", "?0"),
498 ("Upgrade-Insecure-Requests", "1"),
499 ("Connection", "keep-alive"),
500 ]
501}
502
503pub fn chrome_147_headers() -> Vec<(&'static str, &'static str)> {
505 vec![
506 (
507 "User-Agent",
508 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36",
509 ),
510 (
511 "Accept",
512 "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
513 ),
514 ("Accept-Language", "en-US,en;q=0.9"),
515 ("Accept-Encoding", "gzip, deflate, br, zstd"),
516 ("Sec-Fetch-Dest", "document"),
517 ("Sec-Fetch-Mode", "navigate"),
518 ("Sec-Fetch-Site", "none"),
519 ("Sec-Fetch-User", "?1"),
520 (
521 "Sec-Ch-Ua",
522 r#""Google Chrome";v="147", "Not.A/Brand";v="8", "Chromium";v="147""#,
523 ),
524 ("Sec-Ch-Ua-Mobile", "?0"),
525 ("Sec-Ch-Ua-Platform", r#""macOS""#),
526 ("Sec-Ch-Ua-Arch", r#""arm64""#),
527 ("Sec-Ch-Ua-Bitness", r#""64""#),
528 (
529 "Sec-Ch-Ua-Full-Version-List",
530 r#""Google Chrome";v="147.0.7727.138", "Not.A/Brand";v="8.0.0.0", "Chromium";v="147.0.7727.138""#,
531 ),
532 ("Sec-Ch-Ua-Model", r#""""#),
533 ("Sec-Ch-Ua-Platform-Version", r#""15.5.0""#),
534 ("Sec-Ch-Ua-Wow64", "?0"),
535 ("Upgrade-Insecure-Requests", "1"),
536 ("Connection", "keep-alive"),
537 ]
538}
539
540pub fn chrome_147_ajax_headers() -> Vec<(&'static str, &'static str)> {
542 vec![
543 (
544 "User-Agent",
545 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36",
546 ),
547 ("Accept", "application/json, text/plain, */*"),
548 ("Accept-Language", "en-US,en;q=0.9"),
549 ("Accept-Encoding", "gzip, deflate, br, zstd"),
550 ("Content-Type", "application/json"),
551 ("Sec-Fetch-Dest", "empty"),
552 ("Sec-Fetch-Mode", "cors"),
553 ("Sec-Fetch-Site", "same-origin"),
554 (
555 "Sec-Ch-Ua",
556 r#""Google Chrome";v="147", "Not.A/Brand";v="8", "Chromium";v="147""#,
557 ),
558 ("Sec-Ch-Ua-Mobile", "?0"),
559 ("Sec-Ch-Ua-Platform", r#""macOS""#),
560 ("Connection", "keep-alive"),
561 ]
562}
563
564pub fn chrome_147_form_headers() -> Vec<(&'static str, &'static str)> {
566 vec![
567 (
568 "User-Agent",
569 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36",
570 ),
571 (
572 "Accept",
573 "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
574 ),
575 ("Accept-Language", "en-US,en;q=0.9"),
576 ("Accept-Encoding", "gzip, deflate, br, zstd"),
577 ("Content-Type", "application/x-www-form-urlencoded"),
578 ("Sec-Fetch-Dest", "document"),
579 ("Sec-Fetch-Mode", "navigate"),
580 ("Sec-Fetch-Site", "same-origin"),
581 (
582 "Sec-Ch-Ua",
583 r#""Google Chrome";v="147", "Not.A/Brand";v="8", "Chromium";v="147""#,
584 ),
585 ("Sec-Ch-Ua-Mobile", "?0"),
586 ("Sec-Ch-Ua-Platform", r#""macOS""#),
587 ("Sec-Ch-Ua-Arch", r#""arm64""#),
588 ("Sec-Ch-Ua-Bitness", r#""64""#),
589 (
590 "Sec-Ch-Ua-Full-Version-List",
591 r#""Google Chrome";v="147.0.7727.138", "Not.A/Brand";v="8.0.0.0", "Chromium";v="147.0.7727.138""#,
592 ),
593 ("Sec-Ch-Ua-Model", r#""""#),
594 ("Sec-Ch-Ua-Platform-Version", r#""15.5.0""#),
595 ("Sec-Ch-Ua-Wow64", "?0"),
596 ("Upgrade-Insecure-Requests", "1"),
597 ("Connection", "keep-alive"),
598 ]
599}
600
601pub fn chrome_148_headers() -> Vec<(&'static str, &'static str)> {
603 vec![
604 (
605 "User-Agent",
606 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36",
607 ),
608 (
609 "Accept",
610 "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
611 ),
612 ("Accept-Language", "en-US,en;q=0.9"),
613 ("Accept-Encoding", "gzip, deflate, br, zstd"),
614 ("Sec-Fetch-Dest", "document"),
615 ("Sec-Fetch-Mode", "navigate"),
616 ("Sec-Fetch-Site", "none"),
617 ("Sec-Fetch-User", "?1"),
618 (
619 "Sec-Ch-Ua",
620 r#""Chromium";v="148", "Google Chrome";v="148", "Not/A)Brand";v="99""#,
621 ),
622 ("Sec-Ch-Ua-Mobile", "?0"),
623 ("Sec-Ch-Ua-Platform", r#""macOS""#),
624 ("Sec-Ch-Ua-Arch", r#""arm64""#),
625 ("Sec-Ch-Ua-Bitness", r#""64""#),
626 (
627 "Sec-Ch-Ua-Full-Version-List",
628 r#""Chromium";v="148.0.7778.179", "Google Chrome";v="148.0.7778.179", "Not/A)Brand";v="99.0.0.0""#,
629 ),
630 ("Sec-Ch-Ua-Model", r#""""#),
631 ("Sec-Ch-Ua-Platform-Version", r#""15.5.0""#),
632 ("Sec-Ch-Ua-Wow64", "?0"),
633 ("Upgrade-Insecure-Requests", "1"),
634 ("Connection", "keep-alive"),
635 ]
636}
637
638pub fn chrome_148_ajax_headers() -> Vec<(&'static str, &'static str)> {
640 vec![
641 (
642 "User-Agent",
643 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36",
644 ),
645 ("Accept", "application/json, text/plain, */*"),
646 ("Accept-Language", "en-US,en;q=0.9"),
647 ("Accept-Encoding", "gzip, deflate, br, zstd"),
648 ("Content-Type", "application/json"),
649 ("Sec-Fetch-Dest", "empty"),
650 ("Sec-Fetch-Mode", "cors"),
651 ("Sec-Fetch-Site", "same-origin"),
652 (
653 "Sec-Ch-Ua",
654 r#""Chromium";v="148", "Google Chrome";v="148", "Not/A)Brand";v="99""#,
655 ),
656 ("Sec-Ch-Ua-Mobile", "?0"),
657 ("Sec-Ch-Ua-Platform", r#""macOS""#),
658 ("Connection", "keep-alive"),
659 ]
660}
661
662pub fn chrome_148_form_headers() -> Vec<(&'static str, &'static str)> {
664 vec![
665 (
666 "User-Agent",
667 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36",
668 ),
669 (
670 "Accept",
671 "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8",
672 ),
673 ("Accept-Language", "en-US,en;q=0.9"),
674 ("Accept-Encoding", "gzip, deflate, br, zstd"),
675 ("Content-Type", "application/x-www-form-urlencoded"),
676 ("Sec-Fetch-Dest", "document"),
677 ("Sec-Fetch-Mode", "navigate"),
678 ("Sec-Fetch-Site", "same-origin"),
679 (
680 "Sec-Ch-Ua",
681 r#""Chromium";v="148", "Google Chrome";v="148", "Not/A)Brand";v="99""#,
682 ),
683 ("Sec-Ch-Ua-Mobile", "?0"),
684 ("Sec-Ch-Ua-Platform", r#""macOS""#),
685 ("Sec-Ch-Ua-Arch", r#""arm64""#),
686 ("Sec-Ch-Ua-Bitness", r#""64""#),
687 (
688 "Sec-Ch-Ua-Full-Version-List",
689 r#""Chromium";v="148.0.7778.179", "Google Chrome";v="148.0.7778.179", "Not/A)Brand";v="99.0.0.0""#,
690 ),
691 ("Sec-Ch-Ua-Model", r#""""#),
692 ("Sec-Ch-Ua-Platform-Version", r#""15.5.0""#),
693 ("Sec-Ch-Ua-Wow64", "?0"),
694 ("Upgrade-Insecure-Requests", "1"),
695 ("Connection", "keep-alive"),
696 ]
697}
698
699pub fn with_cookies(base: impl Into<Headers>, url: &str, jar: &CookieJar) -> Headers {
701 let base = base.into();
702 let mut builder = HeadersBuilder::from_headers(&base);
703 builder.remove("cookie");
704 if let Some(cookie_header) = jar.build_cookie_header(url) {
705 builder.insert("Cookie", cookie_header);
706 }
707 builder.build()
708}
709
710pub fn with_origin(headers: Headers, origin: &str) -> Headers {
712 let mut builder = HeadersBuilder::from_headers(&headers);
713 builder.remove("origin");
714 builder.insert("Origin", origin);
715 builder.build()
716}
717
718pub fn with_referer(headers: Headers, referer: &str) -> Headers {
720 let mut builder = HeadersBuilder::from_headers(&headers);
721 builder.remove("referer");
722 builder.insert("Referer", referer);
723 builder.build()
724}
725
726pub fn headers_as_refs(headers: &Headers) -> Vec<(&str, &str)> {
728 headers.as_refs()
729}
730
731pub fn headers_to_owned(headers: Vec<(&'static str, &'static str)>) -> Vec<(String, String)> {
733 headers
734 .into_iter()
735 .map(|(k, v)| (k.to_string(), v.to_string()))
736 .collect()
737}
738
739#[derive(Debug, Clone, Copy, PartialEq, Eq)]
741pub struct HeaderSpan {
742 name_start: u32,
743 name_len: u32,
744 value_start: u32,
745 value_len: u32,
746}
747
748impl HeaderSpan {
749 fn name<'a>(&self, buf: &'a [u8]) -> &'a [u8] {
750 let start = self.name_start as usize;
751 &buf[start..start + self.name_len as usize]
752 }
753
754 fn value<'a>(&self, buf: &'a [u8]) -> &'a [u8] {
755 let start = self.value_start as usize;
756 &buf[start..start + self.value_len as usize]
757 }
758}
759
760#[inline]
761fn name_eq_ignore_ascii_case(buf: &[u8], span: &HeaderSpan, name: &[u8]) -> bool {
762 let header_name = span.name(buf);
763 header_name.len() == name.len()
764 && header_name
765 .iter()
766 .zip(name)
767 .all(|(a, b)| a.eq_ignore_ascii_case(b))
768}
769
770fn push_header_bytes(buf: &mut BytesMut, spans: &mut Vec<HeaderSpan>, name: &[u8], value: &[u8]) {
771 let name_start = buf.len() as u32;
772 buf.extend_from_slice(name);
773 let name_len = name.len() as u32;
774 let value_start = buf.len() as u32;
775 buf.extend_from_slice(value);
776 let value_len = value.len() as u32;
777 spans.push(HeaderSpan {
778 name_start,
779 name_len,
780 value_start,
781 value_len,
782 });
783}
784
785#[derive(Debug, Default)]
787pub struct HeadersBuilder {
788 buf: BytesMut,
789 spans: Vec<HeaderSpan>,
790}
791
792impl HeadersBuilder {
793 pub fn new() -> Self {
794 Self::default()
795 }
796
797 pub fn with_capacity(header_count: usize, byte_capacity: usize) -> Self {
798 Self {
799 buf: BytesMut::with_capacity(byte_capacity),
800 spans: Vec::with_capacity(header_count),
801 }
802 }
803
804 pub fn from_headers(headers: &Headers) -> Self {
805 let mut builder = Self::with_capacity(headers.len(), headers.buf.len());
806 for (name, value) in headers.iter_bytes() {
807 builder.push(name, value);
808 }
809 builder
810 }
811
812 pub fn len(&self) -> usize {
813 self.spans.len()
814 }
815
816 pub fn is_empty(&self) -> bool {
817 self.spans.is_empty()
818 }
819
820 pub fn push(&mut self, name: impl AsRef<[u8]>, value: impl AsRef<[u8]>) {
821 push_header_bytes(
822 &mut self.buf,
823 &mut self.spans,
824 name.as_ref(),
825 value.as_ref(),
826 );
827 }
828
829 pub fn append(&mut self, name: impl AsRef<[u8]>, value: impl AsRef<[u8]>) {
830 self.push(name, value);
831 }
832
833 pub fn insert(&mut self, name: impl AsRef<[u8]>, value: impl AsRef<[u8]>) {
834 let name = name.as_ref();
835 self.spans
836 .retain(|span| !name_eq_ignore_ascii_case(&self.buf, span, name));
837 self.push(name, value);
838 }
839
840 pub fn remove(&mut self, name: &str) -> Option<Vec<Vec<u8>>> {
841 let name = name.as_bytes();
842 let mut removed = Vec::new();
843 self.spans.retain(|span| {
844 if name_eq_ignore_ascii_case(&self.buf, span, name) {
845 removed.push(span.value(&self.buf).to_vec());
846 false
847 } else {
848 true
849 }
850 });
851 if removed.is_empty() {
852 None
853 } else {
854 Some(removed)
855 }
856 }
857
858 pub fn get(&self, name: &str) -> Option<&[u8]> {
859 let name = name.as_bytes();
860 self.spans
861 .iter()
862 .find(|span| name_eq_ignore_ascii_case(&self.buf, span, name))
863 .map(|span| span.value(&self.buf))
864 }
865
866 pub fn get_all(&self, name: &str) -> Vec<&[u8]> {
867 let name = name.as_bytes();
868 self.spans
869 .iter()
870 .filter_map(|span| {
871 if name_eq_ignore_ascii_case(&self.buf, span, name) {
872 Some(span.value(&self.buf))
873 } else {
874 None
875 }
876 })
877 .collect()
878 }
879
880 pub fn contains(&self, name: &str) -> bool {
881 self.get(name).is_some()
882 }
883
884 pub fn iter(&self) -> impl Iterator<Item = (&[u8], &[u8])> + '_ {
885 self.spans
886 .iter()
887 .map(|span| (span.name(&self.buf), span.value(&self.buf)))
888 }
889
890 pub fn build(self) -> Headers {
891 Headers {
892 buf: self.buf.freeze(),
893 spans: Arc::new(self.spans),
894 }
895 }
896}
897
898#[derive(Debug, Clone, Default, PartialEq, Eq)]
911pub struct Headers {
912 buf: Bytes,
913 spans: Arc<Vec<HeaderSpan>>,
914}
915
916impl Headers {
917 pub fn new() -> Self {
918 Self::default()
919 }
920
921 pub fn from_vec(headers: Vec<(String, String)>) -> Self {
922 let mut builder = HeadersBuilder::with_capacity(headers.len(), headers.len() * 32);
923 for (name, value) in headers {
924 builder.push(name.as_bytes(), value.as_bytes());
925 }
926 builder.build()
927 }
928
929 pub fn from_static(headers: Vec<(&'static str, &'static str)>) -> Self {
930 let mut builder = HeadersBuilder::with_capacity(headers.len(), headers.len() * 32);
931 for (name, value) in headers {
932 builder.push(name.as_bytes(), value.as_bytes());
933 }
934 builder.build()
935 }
936
937 pub fn len(&self) -> usize {
938 self.spans.len()
939 }
940
941 pub fn is_empty(&self) -> bool {
942 self.spans.is_empty()
943 }
944
945 #[inline]
947 pub fn insert(&mut self, name: impl Into<String>, value: impl Into<String>) {
948 let name = name.into();
949 let value = value.into();
950 self.with_mut(|buf, spans| {
951 spans.retain(|span| !name_eq_ignore_ascii_case(buf, span, name.as_bytes()));
952 push_header_bytes(buf, spans, name.as_bytes(), value.as_bytes());
953 });
954 }
955
956 #[inline]
958 pub fn append(&mut self, name: impl Into<String>, value: impl Into<String>) {
959 let name = name.into();
960 let value = value.into();
961 self.with_mut(|buf, spans| {
962 push_header_bytes(buf, spans, name.as_bytes(), value.as_bytes());
963 });
964 }
965
966 #[inline]
970 pub fn insert_unique(&mut self, name: impl Into<String>, value: impl Into<String>) {
971 let name = name.into();
972 let value = value.into();
973 self.with_mut(|buf, spans| {
974 push_header_bytes(buf, spans, name.as_bytes(), value.as_bytes());
975 });
976 }
977
978 pub fn remove(&mut self, name: &str) -> Option<Vec<String>> {
979 let name_bytes = name.as_bytes();
980 let removed = self.with_mut(|buf, spans| {
981 let mut removed: Vec<String> = Vec::new();
982 spans.retain(|span| {
983 if name_eq_ignore_ascii_case(buf, span, name_bytes) {
984 removed.push(String::from_utf8_lossy(span.value(buf)).into_owned());
985 false
986 } else {
987 true
988 }
989 });
990 removed
991 });
992 if removed.is_empty() {
993 None
994 } else {
995 Some(removed)
996 }
997 }
998
999 #[inline]
1000 pub fn get(&self, name: &str) -> Option<&str> {
1001 let name = name.as_bytes();
1002 self.spans
1003 .iter()
1004 .find(|span| name_eq_ignore_ascii_case(&self.buf, span, name))
1005 .and_then(|span| std::str::from_utf8(span.value(&self.buf)).ok())
1006 }
1007
1008 pub fn get_all(&self, name: &str) -> Vec<&str> {
1009 let name = name.as_bytes();
1010 self.spans
1011 .iter()
1012 .filter_map(|span| {
1013 if name_eq_ignore_ascii_case(&self.buf, span, name) {
1014 std::str::from_utf8(span.value(&self.buf)).ok()
1015 } else {
1016 None
1017 }
1018 })
1019 .collect()
1020 }
1021
1022 #[inline]
1023 pub fn contains(&self, name: &str) -> bool {
1024 let name = name.as_bytes();
1025 self.spans
1026 .iter()
1027 .any(|span| name_eq_ignore_ascii_case(&self.buf, span, name))
1028 }
1029
1030 #[inline]
1031 pub fn iter_bytes(&self) -> impl Iterator<Item = (&[u8], &[u8])> + '_ {
1032 self.spans
1033 .iter()
1034 .map(|span| (span.name(&self.buf), span.value(&self.buf)))
1035 }
1036
1037 pub fn iter(&self) -> impl Iterator<Item = (&str, &str)> + '_ {
1038 self.iter_bytes().filter_map(|(name, value)| {
1039 Some((
1040 std::str::from_utf8(name).ok()?,
1041 std::str::from_utf8(value).ok()?,
1042 ))
1043 })
1044 }
1045
1046 pub fn iter_ordered(&self) -> impl Iterator<Item = (&str, &str)> + '_ {
1047 self.iter()
1048 }
1049
1050 pub fn extend(&mut self, other: Headers) {
1051 let entries: Vec<(Bytes, Bytes)> = other
1054 .iter_bytes()
1055 .map(|(name, value)| (Bytes::copy_from_slice(name), Bytes::copy_from_slice(value)))
1056 .collect();
1057 self.with_mut(|buf, spans| {
1058 for (name, value) in &entries {
1059 push_header_bytes(buf, spans, name, value);
1060 }
1061 });
1062 }
1063
1064 #[inline]
1069 fn with_mut<R>(&mut self, f: impl FnOnce(&mut BytesMut, &mut Vec<HeaderSpan>) -> R) -> R {
1070 let buf = std::mem::take(&mut self.buf);
1071 let mut buf_mut = buf.try_into_mut().unwrap_or_else(|shared| {
1072 let mut owned = BytesMut::with_capacity(shared.len().max(64));
1073 owned.extend_from_slice(&shared);
1074 owned
1075 });
1076 let spans = Arc::make_mut(&mut self.spans);
1077 let result = f(&mut buf_mut, spans);
1078 self.buf = buf_mut.freeze();
1079 result
1080 }
1081
1082 pub fn as_refs(&self) -> Vec<(&str, &str)> {
1083 self.iter().collect()
1084 }
1085
1086 pub fn to_vec(&self) -> Vec<(String, String)> {
1087 self.iter()
1088 .map(|(name, value)| (name.to_string(), value.to_string()))
1089 .collect()
1090 }
1091
1092 pub fn into_inner(self) -> Vec<(String, String)> {
1093 self.to_vec()
1094 }
1095}
1096
1097impl From<Vec<(String, String)>> for Headers {
1098 fn from(value: Vec<(String, String)>) -> Self {
1099 Headers::from_vec(value)
1100 }
1101}
1102
1103impl From<&Headers> for Headers {
1104 fn from(value: &Headers) -> Self {
1105 value.clone()
1106 }
1107}
1108
1109impl From<&[(String, String)]> for Headers {
1110 fn from(value: &[(String, String)]) -> Self {
1111 let mut builder = HeadersBuilder::with_capacity(value.len(), value.len() * 32);
1112 for (name, value) in value {
1113 builder.push(name.as_bytes(), value.as_bytes());
1114 }
1115 builder.build()
1116 }
1117}
1118
1119impl From<&Vec<(String, String)>> for Headers {
1120 fn from(value: &Vec<(String, String)>) -> Self {
1121 Headers::from(value.as_slice())
1122 }
1123}
1124
1125impl<const N: usize> From<&[(String, String); N]> for Headers {
1126 fn from(value: &[(String, String); N]) -> Self {
1127 Headers::from(value.as_slice())
1128 }
1129}
1130
1131impl PartialEq<Vec<(String, String)>> for Headers {
1132 fn eq(&self, other: &Vec<(String, String)>) -> bool {
1133 self.to_vec() == *other
1134 }
1135}
1136
1137impl PartialEq<Headers> for Vec<(String, String)> {
1138 fn eq(&self, other: &Headers) -> bool {
1139 *self == other.to_vec()
1140 }
1141}
1142
1143impl From<HeaderMap> for Headers {
1144 fn from(map: HeaderMap) -> Self {
1145 let mut builder = HeadersBuilder::with_capacity(map.len(), map.len() * 32);
1146 for (name, value) in map.iter() {
1147 builder.append(name.as_str(), value.as_bytes());
1148 }
1149 builder.build()
1150 }
1151}
1152
1153impl From<HeadersBuilder> for Headers {
1154 fn from(builder: HeadersBuilder) -> Self {
1155 builder.build()
1156 }
1157}
1158
1159#[derive(Debug)]
1171pub struct OrderedHeaders {
1172 headers: Headers,
1173 cached_pairs: OnceLock<Arc<[(String, String)]>>,
1174}
1175
1176impl Clone for OrderedHeaders {
1177 fn clone(&self) -> Self {
1178 Self {
1179 headers: self.headers.clone(),
1180 cached_pairs: OnceLock::new(),
1181 }
1182 }
1183}
1184
1185static CHROME_NAVIGATION_HEADERS: OnceLock<OrderedHeaders> = OnceLock::new();
1186static FIREFOX_NAVIGATION_HEADERS: OnceLock<OrderedHeaders> = OnceLock::new();
1187
1188impl OrderedHeaders {
1189 pub fn new(headers: Vec<(String, String)>) -> Self {
1191 Self {
1192 headers: Headers::from_vec(headers),
1193 cached_pairs: OnceLock::new(),
1194 }
1195 }
1196
1197 pub fn chrome_navigation() -> Self {
1200 CHROME_NAVIGATION_HEADERS
1201 .get_or_init(|| Self::new(headers_to_owned(chrome_148_headers())))
1202 .clone()
1203 }
1204
1205 pub fn firefox_navigation() -> Self {
1208 FIREFOX_NAVIGATION_HEADERS
1209 .get_or_init(|| Self::new(headers_to_owned(firefox_151_headers())))
1210 .clone()
1211 }
1212
1213 pub fn headers(&self) -> &[(String, String)] {
1215 self.cached_pairs
1216 .get_or_init(|| {
1217 let pairs = self.headers.to_vec();
1218 Arc::from(pairs.into_boxed_slice())
1219 })
1220 .as_ref()
1221 }
1222
1223 pub fn headers_ref(&self) -> &Headers {
1225 &self.headers
1226 }
1227
1228 pub fn ja4h_fingerprint(&self) -> String {
1234 use sha2::{Digest, Sha256};
1235
1236 let header_names: Vec<String> = self
1237 .headers
1238 .iter()
1239 .map(|(name, _)| name.to_lowercase())
1240 .collect();
1241
1242 let names_str = header_names.join(",");
1243
1244 let mut hasher = Sha256::new();
1245 hasher.update(names_str.as_bytes());
1246 let hash = hasher.finalize();
1247
1248 let hash_str: String = hash[..3].iter().map(|b| format!("{:02x}", b)).collect();
1249
1250 format!("{}|{}", names_str, hash_str)
1251 }
1252
1253 pub fn add(mut self, name: impl Into<String>, value: impl Into<String>) -> Self {
1255 self.headers.append(name, value);
1256 self
1257 }
1258
1259 pub fn into_vec(self) -> Vec<(String, String)> {
1261 self.headers.into_inner()
1262 }
1263}
1264
1265impl From<Vec<(String, String)>> for OrderedHeaders {
1266 fn from(headers: Vec<(String, String)>) -> Self {
1267 Self::new(headers)
1268 }
1269}
1270
1271impl From<OrderedHeaders> for Vec<(String, String)> {
1272 fn from(oh: OrderedHeaders) -> Self {
1273 oh.into_vec()
1274 }
1275}
1276
1277fn firefox_navigation_headers(ua: &'static str) -> Vec<(&'static str, &'static str)> {
1278 vec![
1279 ("User-Agent", ua),
1280 (
1281 "Accept",
1282 "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
1283 ),
1284 ("Accept-Language", "en-US,en;q=0.5"),
1285 ("Accept-Encoding", "gzip, deflate, br, zstd"),
1286 ("Sec-Fetch-Dest", "document"),
1287 ("Sec-Fetch-Mode", "navigate"),
1288 ("Sec-Fetch-Site", "none"),
1289 ("Sec-Fetch-User", "?1"),
1290 ("Upgrade-Insecure-Requests", "1"),
1291 ("Connection", "keep-alive"),
1292 ]
1293}
1294
1295fn firefox_ajax_headers(ua: &'static str) -> Vec<(&'static str, &'static str)> {
1296 vec![
1297 ("User-Agent", ua),
1298 ("Accept", "application/json, text/plain, */*"),
1299 ("Accept-Language", "en-US,en;q=0.5"),
1300 ("Accept-Encoding", "gzip, deflate, br, zstd"),
1301 ("Content-Type", "application/json"),
1302 ("Sec-Fetch-Dest", "empty"),
1303 ("Sec-Fetch-Mode", "cors"),
1304 ("Sec-Fetch-Site", "same-origin"),
1305 ("Connection", "keep-alive"),
1306 ]
1307}
1308
1309fn firefox_form_headers(ua: &'static str) -> Vec<(&'static str, &'static str)> {
1310 vec![
1311 ("User-Agent", ua),
1312 (
1313 "Accept",
1314 "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
1315 ),
1316 ("Accept-Language", "en-US,en;q=0.5"),
1317 ("Accept-Encoding", "gzip, deflate, br, zstd"),
1318 ("Content-Type", "application/x-www-form-urlencoded"),
1319 ("Sec-Fetch-Dest", "document"),
1320 ("Sec-Fetch-Mode", "navigate"),
1321 ("Sec-Fetch-Site", "same-origin"),
1322 ("Upgrade-Insecure-Requests", "1"),
1323 ("Connection", "keep-alive"),
1324 ]
1325}
1326
1327macro_rules! firefox_header_set {
1328 ($headers_fn:ident, $ajax_fn:ident, $form_fn:ident, $ua:literal, $label:literal) => {
1329 #[doc = concat!("Firefox ", $label, " browser headers for page navigation.")]
1330 #[doc = "Firefox does NOT send Sec-Ch-Ua headers (Client Hints)."]
1331 pub fn $headers_fn() -> Vec<(&'static str, &'static str)> {
1332 firefox_navigation_headers($ua)
1333 }
1334
1335 #[doc = concat!("Firefox ", $label, " headers for AJAX/API requests.")]
1336 pub fn $ajax_fn() -> Vec<(&'static str, &'static str)> {
1337 firefox_ajax_headers($ua)
1338 }
1339
1340 #[doc = concat!("Firefox ", $label, " headers for form submissions.")]
1341 pub fn $form_fn() -> Vec<(&'static str, &'static str)> {
1342 firefox_form_headers($ua)
1343 }
1344 };
1345}
1346
1347firefox_header_set!(
1348 firefox_133_headers,
1349 firefox_133_ajax_headers,
1350 firefox_133_form_headers,
1351 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:133.0) Gecko/20100101 Firefox/133.0",
1352 "133"
1353);
1354firefox_header_set!(
1355 firefox_134_headers,
1356 firefox_134_ajax_headers,
1357 firefox_134_form_headers,
1358 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:134.0) Gecko/20100101 Firefox/134.0",
1359 "134"
1360);
1361firefox_header_set!(
1362 firefox_135_headers,
1363 firefox_135_ajax_headers,
1364 firefox_135_form_headers,
1365 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:135.0) Gecko/20100101 Firefox/135.0",
1366 "135"
1367);
1368firefox_header_set!(
1369 firefox_136_headers,
1370 firefox_136_ajax_headers,
1371 firefox_136_form_headers,
1372 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:136.0) Gecko/20100101 Firefox/136.0",
1373 "136"
1374);
1375firefox_header_set!(
1376 firefox_137_headers,
1377 firefox_137_ajax_headers,
1378 firefox_137_form_headers,
1379 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:137.0) Gecko/20100101 Firefox/137.0",
1380 "137"
1381);
1382firefox_header_set!(
1383 firefox_138_headers,
1384 firefox_138_ajax_headers,
1385 firefox_138_form_headers,
1386 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:138.0) Gecko/20100101 Firefox/138.0",
1387 "138"
1388);
1389firefox_header_set!(
1390 firefox_139_headers,
1391 firefox_139_ajax_headers,
1392 firefox_139_form_headers,
1393 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:139.0) Gecko/20100101 Firefox/139.0",
1394 "139"
1395);
1396firefox_header_set!(
1397 firefox_140_headers,
1398 firefox_140_ajax_headers,
1399 firefox_140_form_headers,
1400 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:140.0) Gecko/20100101 Firefox/140.0",
1401 "140"
1402);
1403firefox_header_set!(
1404 firefox_141_headers,
1405 firefox_141_ajax_headers,
1406 firefox_141_form_headers,
1407 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:141.0) Gecko/20100101 Firefox/141.0",
1408 "141"
1409);
1410firefox_header_set!(
1411 firefox_142_headers,
1412 firefox_142_ajax_headers,
1413 firefox_142_form_headers,
1414 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:142.0) Gecko/20100101 Firefox/142.0",
1415 "142"
1416);
1417firefox_header_set!(
1418 firefox_143_headers,
1419 firefox_143_ajax_headers,
1420 firefox_143_form_headers,
1421 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:143.0) Gecko/20100101 Firefox/143.0",
1422 "143"
1423);
1424firefox_header_set!(
1425 firefox_144_headers,
1426 firefox_144_ajax_headers,
1427 firefox_144_form_headers,
1428 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:144.0) Gecko/20100101 Firefox/144.0",
1429 "144"
1430);
1431firefox_header_set!(
1432 firefox_145_headers,
1433 firefox_145_ajax_headers,
1434 firefox_145_form_headers,
1435 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:145.0) Gecko/20100101 Firefox/145.0",
1436 "145"
1437);
1438firefox_header_set!(
1439 firefox_146_headers,
1440 firefox_146_ajax_headers,
1441 firefox_146_form_headers,
1442 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:146.0) Gecko/20100101 Firefox/146.0",
1443 "146"
1444);
1445firefox_header_set!(
1446 firefox_147_headers,
1447 firefox_147_ajax_headers,
1448 firefox_147_form_headers,
1449 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:147.0) Gecko/20100101 Firefox/147.0",
1450 "147"
1451);
1452firefox_header_set!(
1453 firefox_148_headers,
1454 firefox_148_ajax_headers,
1455 firefox_148_form_headers,
1456 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:148.0) Gecko/20100101 Firefox/148.0",
1457 "148"
1458);
1459firefox_header_set!(
1460 firefox_149_headers,
1461 firefox_149_ajax_headers,
1462 firefox_149_form_headers,
1463 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:149.0) Gecko/20100101 Firefox/149.0",
1464 "149"
1465);
1466firefox_header_set!(
1467 firefox_150_headers,
1468 firefox_150_ajax_headers,
1469 firefox_150_form_headers,
1470 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:150.0) Gecko/20100101 Firefox/150.0",
1471 "150"
1472);
1473firefox_header_set!(
1474 firefox_151_headers,
1475 firefox_151_ajax_headers,
1476 firefox_151_form_headers,
1477 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:151.0) Gecko/20100101 Firefox/151.0",
1478 "151"
1479);
1480firefox_header_set!(
1481 firefox_esr_115_headers,
1482 firefox_esr_115_ajax_headers,
1483 firefox_esr_115_form_headers,
1484 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:115.0) Gecko/20100101 Firefox/115.0",
1485 "115 ESR"
1486);
1487firefox_header_set!(
1488 firefox_esr_128_headers,
1489 firefox_esr_128_ajax_headers,
1490 firefox_esr_128_form_headers,
1491 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:128.0) Gecko/20100101 Firefox/128.0",
1492 "128 ESR"
1493);
1494firefox_header_set!(
1495 firefox_esr_140_headers,
1496 firefox_esr_140_ajax_headers,
1497 firefox_esr_140_form_headers,
1498 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:140.0) Gecko/20100101 Firefox/140.0",
1499 "140 ESR"
1500);