1#[derive(Clone, Debug, PartialEq)]
2pub struct Signature {
3 pub version: Version,
5 pub horder: Vec<Header>,
7 pub habsent: Vec<Header>,
9 pub expsw: String,
11}
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14pub enum HttpMatchQuality {
15 High,
16 Medium,
17 Low,
18 Bad,
19}
20
21impl HttpMatchQuality {
22 pub fn as_score(self) -> u32 {
23 match self {
24 HttpMatchQuality::High => 0,
25 HttpMatchQuality::Medium => 1,
26 HttpMatchQuality::Low => 2,
27 HttpMatchQuality::Bad => 3,
28 }
29 }
30}
31
32impl crate::db_matching_trait::MatchQuality for HttpMatchQuality {
33 const MAX_DISTANCE: u32 = 12;
35
36 fn distance_to_score(distance: u32) -> f32 {
37 match distance {
38 0 => 1.0,
39 1 => 0.95,
40 2 => 0.90,
41 3 => 0.80,
42 4..=5 => 0.70,
43 6..=7 => 0.60,
44 8..=9 => 0.40,
45 10..=11 => 0.20,
46 d if d <= Self::MAX_DISTANCE => 0.10,
47 _ => 0.05,
48 }
49 }
50}
51
52#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
56pub enum Version {
57 V10,
59 V11,
61 V20,
63 V30,
65 Any,
67}
68
69impl Version {
70 pub fn parse(version_str: &str) -> Option<Self> {
71 match version_str {
72 "HTTP/1.0" => Some(Version::V10),
73 "HTTP/1.1" => Some(Version::V11),
74 "HTTP/2" | "HTTP/2.0" => Some(Version::V20),
75 "HTTP/3" | "HTTP/3.0" => Some(Version::V30),
76 _ => None,
77 }
78 }
79}
80
81impl std::str::FromStr for Version {
82 type Err = ();
83
84 fn from_str(s: &str) -> Result<Self, Self::Err> {
85 Self::parse(s).ok_or(())
86 }
87}
88
89impl Version {
90 pub fn as_str(&self) -> &'static str {
91 match self {
92 Version::V10 => "HTTP/1.0",
93 Version::V11 => "HTTP/1.1",
94 Version::V20 => "HTTP/2",
95 Version::V30 => "HTTP/3",
96 Version::Any => "Any",
97 }
98 }
99}
100
101#[derive(Clone, Debug, PartialEq)]
102pub struct Header {
103 pub optional: bool,
104 pub name: String,
105 pub value: Option<String>,
106}
107
108#[derive(Clone, Debug, PartialEq)]
109pub enum HttpDiagnosis {
110 Dishonest,
111 Anonymous,
112 Generic,
113 None,
114}
115
116impl Header {
117 pub fn new<S: AsRef<str>>(name: S) -> Self {
118 Header { optional: false, name: name.as_ref().to_owned(), value: None }
119 }
120
121 pub fn with_value<S: AsRef<str>>(mut self, value: S) -> Self {
122 self.value = Some(value.as_ref().to_owned());
123 self
124 }
125
126 pub fn with_optional_value<S: AsRef<str>>(mut self, value: Option<S>) -> Self {
127 self.value = value.map(|v| v.as_ref().to_owned());
128 self
129 }
130
131 pub fn optional(mut self) -> Self {
132 self.optional = true;
133 self
134 }
135}
136
137pub fn request_optional_headers() -> Vec<&'static str> {
138 vec![
139 "Cookie",
140 "Referer",
141 "Origin",
142 "Range",
143 "If-Modified-Since",
144 "If-None-Match",
145 "Via",
146 "X-Forwarded-For",
147 "Authorization",
148 "Proxy-Authorization",
149 "Cache-Control",
150 ]
151}
152
153pub fn response_optional_headers() -> Vec<&'static str> {
154 vec![
155 "Set-Cookie",
156 "Last-Modified",
157 "ETag",
158 "Content-Length",
159 "Content-Disposition",
160 "Cache-Control",
161 "Expires",
162 "Pragma",
163 "Location",
164 "Refresh",
165 "Content-Range",
166 "Vary",
167 ]
168}
169
170pub fn request_skip_value_headers() -> Vec<&'static str> {
171 vec!["Host", "User-Agent"]
172}
173
174pub fn response_skip_value_headers() -> Vec<&'static str> {
175 vec!["Date", "Content-Type", "Server"]
176}
177
178pub fn request_common_headers() -> Vec<&'static str> {
179 vec![
180 "Host",
181 "User-Agent",
182 "Connection",
183 "Accept",
184 "Accept-Encoding",
185 "Accept-Language",
186 "Accept-Charset",
187 "Keep-Alive",
188 ]
189}
190
191pub fn response_common_headers() -> Vec<&'static str> {
192 vec!["Content-Type", "Connection", "Keep-Alive", "Accept-Ranges", "Date"]
193}