viewpoint_core/network/har/
mod.rs1use std::collections::HashMap;
7
8pub use super::har_types::{
10 Har, HarCache, HarCacheEntry, HarContent, HarCookie, HarCreator, HarEntry, HarHeader, HarLog,
11 HarPage, HarPageTimings, HarParam, HarPostData, HarQueryParam, HarRequest, HarResponse,
12 HarTimings,
13};
14
15impl Har {
16 pub fn new(creator_name: &str, creator_version: &str) -> Self {
18 Self {
19 log: HarLog {
20 version: "1.2".to_string(),
21 creator: HarCreator {
22 name: creator_name.to_string(),
23 version: creator_version.to_string(),
24 },
25 browser: None,
26 pages: Vec::new(),
27 entries: Vec::new(),
28 comment: None,
29 },
30 }
31 }
32
33 pub fn add_page(&mut self, page: HarPage) {
35 self.log.pages.push(page);
36 }
37
38 pub fn add_entry(&mut self, entry: HarEntry) {
40 self.log.entries.push(entry);
41 }
42
43 pub fn set_browser(&mut self, name: &str, version: &str) {
45 self.log.browser = Some(HarCreator {
46 name: name.to_string(),
47 version: version.to_string(),
48 });
49 }
50}
51
52impl HarPage {
53 pub fn new(id: &str, title: &str, started: &str) -> Self {
55 Self {
56 started_date_time: started.to_string(),
57 id: id.to_string(),
58 title: title.to_string(),
59 page_timings: HarPageTimings::default(),
60 comment: None,
61 }
62 }
63
64 pub fn set_timings(&mut self, on_content_load: Option<f64>, on_load: Option<f64>) {
66 self.page_timings.on_content_load = on_content_load;
67 self.page_timings.on_load = on_load;
68 }
69}
70
71impl HarEntry {
72 pub fn new(started: &str) -> Self {
74 Self {
75 pageref: None,
76 started_date_time: started.to_string(),
77 time: 0.0,
78 request: HarRequest::default(),
79 response: HarResponse::default(),
80 cache: HarCache::default(),
81 timings: HarTimings::default(),
82 server_ip_address: None,
83 connection: None,
84 comment: None,
85 }
86 }
87
88 pub fn set_request(&mut self, request: HarRequest) {
90 self.request = request;
91 }
92
93 pub fn set_response(&mut self, response: HarResponse) {
95 self.response = response;
96 }
97
98 pub fn set_timings(&mut self, timings: HarTimings) {
100 self.time = timings.total();
101 self.timings = timings;
102 }
103
104 pub fn set_server_ip(&mut self, ip: &str) {
106 self.server_ip_address = Some(ip.to_string());
107 }
108}
109
110impl HarRequest {
111 pub fn new(method: &str, url: &str) -> Self {
113 Self {
114 method: method.to_string(),
115 url: url.to_string(),
116 http_version: "HTTP/1.1".to_string(),
117 cookies: Vec::new(),
118 headers: Vec::new(),
119 query_string: Vec::new(),
120 post_data: None,
121 headers_size: -1,
122 body_size: -1,
123 comment: None,
124 }
125 }
126
127 pub fn set_headers(&mut self, headers: &HashMap<String, String>) {
129 self.headers = headers
130 .iter()
131 .map(|(name, value)| HarHeader {
132 name: name.clone(),
133 value: value.clone(),
134 })
135 .collect();
136
137 self.headers_size = self
139 .headers
140 .iter()
141 .map(|h| (h.name.len() + h.value.len() + 4) as i64) .sum();
143 }
144
145 pub fn set_post_data(&mut self, data: Option<&str>, mime_type: Option<&str>) {
147 if let Some(text) = data {
148 self.post_data = Some(HarPostData {
149 mime_type: mime_type.unwrap_or("application/octet-stream").to_string(),
150 text: text.to_string(),
151 params: None,
152 });
153 self.body_size = text.len() as i64;
154 }
155 }
156
157 pub fn parse_query_string(&mut self) {
159 if let Ok(url) = url::Url::parse(&self.url) {
160 self.query_string = url
161 .query_pairs()
162 .map(|(name, value)| HarQueryParam {
163 name: name.to_string(),
164 value: value.to_string(),
165 })
166 .collect();
167 }
168 }
169}
170
171impl HarResponse {
172 pub fn new(status: i32, status_text: &str) -> Self {
174 Self {
175 status,
176 status_text: status_text.to_string(),
177 http_version: "HTTP/1.1".to_string(),
178 cookies: Vec::new(),
179 headers: Vec::new(),
180 content: HarContent::default(),
181 redirect_url: String::new(),
182 headers_size: -1,
183 body_size: -1,
184 comment: None,
185 }
186 }
187
188 pub fn error(error_text: &str) -> Self {
190 Self {
191 status: 0,
192 status_text: error_text.to_string(),
193 http_version: "HTTP/1.1".to_string(),
194 cookies: Vec::new(),
195 headers: Vec::new(),
196 content: HarContent {
197 size: 0,
198 compression: None,
199 mime_type: "x-unknown".to_string(),
200 text: Some(error_text.to_string()),
201 encoding: None,
202 comment: None,
203 },
204 redirect_url: String::new(),
205 headers_size: -1,
206 body_size: -1,
207 comment: None,
208 }
209 }
210
211 pub fn set_headers(&mut self, headers: &HashMap<String, String>) {
213 self.headers = headers
214 .iter()
215 .map(|(name, value)| HarHeader {
216 name: name.clone(),
217 value: value.clone(),
218 })
219 .collect();
220
221 self.headers_size = self
223 .headers
224 .iter()
225 .map(|h| (h.name.len() + h.value.len() + 4) as i64)
226 .sum();
227 }
228
229 pub fn set_content(&mut self, text: Option<&str>, mime_type: &str, encoding: Option<&str>) {
231 self.content = HarContent {
232 size: text.map_or(0, |t| t.len() as i64),
233 compression: None,
234 mime_type: mime_type.to_string(),
235 text: text.map(String::from),
236 encoding: encoding.map(String::from),
237 comment: None,
238 };
239 self.body_size = self.content.size;
240 }
241
242 pub fn set_cookies(&mut self, cookies: &[(String, String)]) {
244 self.cookies = cookies
245 .iter()
246 .map(|(name, value)| HarCookie {
247 name: name.clone(),
248 value: value.clone(),
249 ..Default::default()
250 })
251 .collect();
252 }
253
254 pub fn set_redirect_url(&mut self, url: &str) {
256 self.redirect_url = url.to_string();
257 }
258}
259
260impl HarTimings {
261 pub fn total(&self) -> f64 {
263 let mut total = 0.0;
264 if self.blocked > 0.0 {
265 total += self.blocked;
266 }
267 if self.dns > 0.0 {
268 total += self.dns;
269 }
270 if self.connect > 0.0 {
271 total += self.connect;
272 }
273 if self.send > 0.0 {
274 total += self.send;
275 }
276 if self.wait > 0.0 {
277 total += self.wait;
278 }
279 if self.receive > 0.0 {
280 total += self.receive;
281 }
282 total
283 }
284
285 pub fn from_resource_timing(
287 dns_start: f64,
288 dns_end: f64,
289 connect_start: f64,
290 connect_end: f64,
291 ssl_start: f64,
292 ssl_end: f64,
293 send_start: f64,
294 send_end: f64,
295 receive_headers_end: f64,
296 ) -> Self {
297 Self {
298 blocked: if dns_start > 0.0 { dns_start } else { -1.0 },
299 dns: if dns_end > dns_start {
300 dns_end - dns_start
301 } else {
302 -1.0
303 },
304 connect: if connect_end > connect_start && ssl_start <= 0.0 {
305 connect_end - connect_start
306 } else if connect_end > connect_start {
307 ssl_start - connect_start
308 } else {
309 -1.0
310 },
311 ssl: if ssl_end > ssl_start {
312 ssl_end - ssl_start
313 } else {
314 -1.0
315 },
316 send: if send_end > send_start {
317 send_end - send_start
318 } else {
319 -1.0
320 },
321 wait: if receive_headers_end > send_end {
322 receive_headers_end - send_end
323 } else {
324 -1.0
325 },
326 receive: -1.0, comment: None,
328 }
329 }
330}