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
116#[cfg(test)]
117pub fn header<S: AsRef<str>>(name: S) -> Header {
118 Header::new(name)
119}
120
121impl Header {
122 pub fn new<S: AsRef<str>>(name: S) -> Self {
123 Header {
124 optional: false,
125 name: name.as_ref().to_owned(),
126 value: None,
127 }
128 }
129
130 pub fn with_value<S: AsRef<str>>(mut self, value: S) -> Self {
131 self.value = Some(value.as_ref().to_owned());
132 self
133 }
134
135 pub fn with_optional_value<S: AsRef<str>>(mut self, value: Option<S>) -> Self {
136 self.value = value.map(|v| v.as_ref().to_owned());
137 self
138 }
139
140 pub fn optional(mut self) -> Self {
141 self.optional = true;
142 self
143 }
144}
145
146pub fn request_optional_headers() -> Vec<&'static str> {
147 vec![
148 "Cookie",
149 "Referer",
150 "Origin",
151 "Range",
152 "If-Modified-Since",
153 "If-None-Match",
154 "Via",
155 "X-Forwarded-For",
156 "Authorization",
157 "Proxy-Authorization",
158 "Cache-Control",
159 ]
160}
161
162pub fn response_optional_headers() -> Vec<&'static str> {
163 vec![
164 "Set-Cookie",
165 "Last-Modified",
166 "ETag",
167 "Content-Length",
168 "Content-Disposition",
169 "Cache-Control",
170 "Expires",
171 "Pragma",
172 "Location",
173 "Refresh",
174 "Content-Range",
175 "Vary",
176 ]
177}
178
179pub fn request_skip_value_headers() -> Vec<&'static str> {
180 vec!["Host", "User-Agent"]
181}
182
183pub fn response_skip_value_headers() -> Vec<&'static str> {
184 vec!["Date", "Content-Type", "Server"]
185}
186
187pub fn request_common_headers() -> Vec<&'static str> {
188 vec![
189 "Host",
190 "User-Agent",
191 "Connection",
192 "Accept",
193 "Accept-Encoding",
194 "Accept-Language",
195 "Accept-Charset",
196 "Keep-Alive",
197 ]
198}
199
200pub fn response_common_headers() -> Vec<&'static str> {
201 vec![
202 "Content-Type",
203 "Connection",
204 "Keep-Alive",
205 "Accept-Ranges",
206 "Date",
207 ]
208}