http_protocol/header/
utils.rs1use crate::header::{Header, HeaderError};
2use lazy_static::lazy_static;
3
4#[derive(Debug, PartialEq)]
5pub struct HeaderChar {
6 char_code: u8,
7 next_char: Vec<HeaderChar>,
8 header: Option<Header>,
9}
10
11fn add_header(header_chars: &mut Vec<HeaderChar>, header: &[u8], header_enum: Header) {
12 let mut ptr = header_chars;
13 let header_enum_value = header.to_ascii_lowercase();
14 let end_idx = header_enum_value.len() - 1;
15 for (idx, char_code) in header_enum_value.iter().enumerate() {
16 let mut search_result =
17 ptr.binary_search_by(|header_char| (header_char.char_code).cmp(char_code));
18 if search_result.is_err() {
19 let header = if idx == end_idx {
20 Some(header_enum.clone())
21 } else {
22 None
23 };
24 ptr.push(HeaderChar {
25 char_code: *char_code,
26 next_char: Vec::new(),
27 header,
28 });
29 ptr.sort_unstable_by(|a, b| a.char_code.cmp(&b.char_code));
30 search_result =
31 ptr.binary_search_by(|header_char| (header_char.char_code).cmp(char_code));
32 }
33 let index = search_result.unwrap();
34 ptr = &mut ptr[index].next_char;
35 }
36}
37
38lazy_static! {
39 pub static ref HEADER_CHARS: Vec<HeaderChar> = {
40 let mut h = Vec::<HeaderChar>::new();
41 add_header(&mut h, b"Referer", Header::Referer);
42 add_header(&mut h, b"Pragma", Header::Pragma);
43 add_header(&mut h, b"Upgrade", Header::Upgrade);
44 add_header(&mut h, b"Content-Type", Header::ContentType);
45 add_header(&mut h, b"Content-Length", Header::ContentLength);
46 add_header(&mut h, b"Content-Encoding", Header::ContentEncoding);
47 add_header(&mut h, b"Authorization", Header::Authorization);
48 add_header(&mut h, b"Accept", Header::Accept);
49 add_header(&mut h, b"Accept-Encoding", Header::AcceptEncoding);
50 add_header(&mut h, b"Accept-Language", Header::AcceptLanguage);
51 add_header(&mut h, b"Sec-Fetch-Dest", Header::SecFetchDest);
52 add_header(&mut h, b"Sec-Fetch-User", Header::SecFetchUser);
53 add_header(&mut h, b"Sec-Fetch-Site", Header::SecFetchSite);
54 add_header(&mut h, b"Sec-Fetch-Mode", Header::SecFetchMode);
55 add_header(&mut h, b"Host", Header::Host);
56 add_header(&mut h, b"Cache-Control", Header::CacheControl);
57 add_header(&mut h, b"Connection", Header::Connection);
58 add_header(&mut h, b"User-Agent", Header::UserAgent);
59 add_header(
60 &mut h,
61 b"Upgrade-Insecure-Requests",
62 Header::UpgradeInsecureRequests,
63 );
64 h
65 };
66}
67
68pub fn get_header(value: &[u8]) -> Result<Header, HeaderError> {
69 let lowercase_value = value.to_ascii_lowercase();
70 let mut ptr = &*HEADER_CHARS;
71 let end_idx = lowercase_value.len() - 1;
72 for (idx, char_code) in lowercase_value.iter().enumerate() {
73 let search_result =
74 ptr.binary_search_by(|header_char| (header_char.char_code).cmp(&char_code));
75 let index = search_result.map_err(|_| HeaderError::InvalidHeader)?;
76 if idx == end_idx {
77 return ptr[index].header.clone().ok_or(HeaderError::InvalidHeader);
78 }
79 ptr = &ptr[index].next_char;
80 }
81 Err(HeaderError::InvalidHeader)
82}
83
84pub fn check_header_value(v: &[u8]) -> Result<(), HeaderError> {
85 for e in v.iter() {
86 if *e < 32 || *e > 126 {
87 return Err(HeaderError::InvalidHeaderValue);
88 }
89 }
90 Ok(())
91}