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