1use chrono::prelude::*;
2use std::collections::HashMap;
3
4const X_ACCESS_LEVEL: &str = "x-access-level";
5const X_APP_LIMIT_24HOUR_LIMIT: &str = "x-app-limit-24hour-limit";
6const X_APP_LIMIT_24HOUR_RESET: &str = "x-app-limit-24hour-reset";
7const X_APP_LIMIT_24HOUR_REMAINING: &str = "x-app-limit-24hour-remaining";
8const X_CONNECTION_HASH: &str = "x-connection-hash";
9const X_CONTENT_TYPE_OPTIONS: &str = "x-content-type-options";
10const X_FRAME_OPTIONS: &str = "x-frame-options";
11const X_RATE_LIMIT_LIMIT: &str = "x-rate-limit-limit";
12const X_RATE_LIMIT_RESET: &str = "x-rate-limit-reset";
13const X_RATE_LIMIT_REMAINING: &str = "x-rate-limit-remaining";
14const X_RESPONSE_TIME: &str = "x-response-time";
15const X_TRANSACTION_ID: &str = "x-transaction-id";
16const X_USER_LIMIT_24HOUR_LIMIT: &str = "x-user-limit-24hour-limit";
17const X_USER_LIMIT_24HOUR_RESET: &str = "x-user-limit-24hour-reset";
18const X_USER_LIMIT_24HOUR_REMAINING: &str = "x-user-limit-24hour-remaining";
19const X_XSS_PROTECTION: &str = "x-xss-protection";
20
21const KEYS: [&str; 16] = [
22 X_ACCESS_LEVEL,
23 X_APP_LIMIT_24HOUR_LIMIT,
24 X_APP_LIMIT_24HOUR_RESET,
25 X_APP_LIMIT_24HOUR_REMAINING,
26 X_CONNECTION_HASH,
27 X_CONTENT_TYPE_OPTIONS,
28 X_FRAME_OPTIONS,
29 X_RATE_LIMIT_LIMIT,
30 X_RATE_LIMIT_RESET,
31 X_RATE_LIMIT_REMAINING,
32 X_RESPONSE_TIME,
33 X_TRANSACTION_ID,
34 X_USER_LIMIT_24HOUR_LIMIT,
35 X_USER_LIMIT_24HOUR_RESET,
36 X_USER_LIMIT_24HOUR_REMAINING,
37 X_XSS_PROTECTION,
38];
39
40#[derive(Debug, Clone)]
41pub struct Headers {
42 pub x_access_level: Option<String>,
43 pub x_app_limit_24hour_limit: Option<u64>,
44 pub x_app_limit_24hour_reset: Option<DateTime<Utc>>,
45 pub x_app_limit_24hour_remaining: Option<u64>,
46 pub x_connection_hash: Option<String>,
47 pub x_content_type_options: Option<String>,
48 pub x_frame_options: Option<String>,
49 pub x_rate_limit_limit: Option<u64>,
50 pub x_rate_limit_reset: Option<DateTime<Utc>>,
51 pub x_rate_limit_remaining: Option<u64>,
52 pub x_response_time: Option<u64>,
53 pub x_transaction_id: Option<String>,
54 pub x_user_limit_24hour_limit: Option<u64>,
55 pub x_user_limit_24hour_reset: Option<DateTime<Utc>>,
56 pub x_user_limit_24hour_remaining: Option<u64>,
57 pub x_xss_protection: Option<u64>,
58 pub extra: HashMap<String, String>,
59}
60
61impl Headers {
62 pub fn new(header: &reqwest::header::HeaderMap) -> Self {
63 let mut extra = HashMap::new();
64 for (name, value) in header.iter() {
65 if !KEYS.contains(&name.as_str())
66 && let Ok(value) = value.to_str()
67 {
68 extra.insert(name.as_str().to_string(), value.to_string());
69 }
70 }
71 Self {
72 x_access_level: get_string_value(header, X_ACCESS_LEVEL),
73 x_app_limit_24hour_limit: get_integer_value(header, X_APP_LIMIT_24HOUR_LIMIT),
74 x_app_limit_24hour_reset: get_unixtimestamp_value(header, X_APP_LIMIT_24HOUR_RESET),
75 x_app_limit_24hour_remaining: get_integer_value(header, X_APP_LIMIT_24HOUR_REMAINING),
76 x_connection_hash: get_string_value(header, X_CONNECTION_HASH),
77 x_content_type_options: get_string_value(header, X_CONTENT_TYPE_OPTIONS),
78 x_frame_options: get_string_value(header, X_FRAME_OPTIONS),
79 x_rate_limit_limit: get_integer_value(header, X_RATE_LIMIT_LIMIT),
80 x_rate_limit_reset: get_unixtimestamp_value(header, X_RATE_LIMIT_RESET),
81 x_rate_limit_remaining: get_integer_value(header, X_RATE_LIMIT_REMAINING),
82 x_response_time: get_integer_value(header, X_RESPONSE_TIME),
83 x_transaction_id: get_string_value(header, X_TRANSACTION_ID),
84 x_user_limit_24hour_limit: get_integer_value(header, X_USER_LIMIT_24HOUR_LIMIT),
85 x_user_limit_24hour_reset: get_unixtimestamp_value(header, X_USER_LIMIT_24HOUR_RESET),
86 x_user_limit_24hour_remaining: get_integer_value(header, X_USER_LIMIT_24HOUR_REMAINING),
87 x_xss_protection: get_integer_value(header, X_XSS_PROTECTION),
88 extra,
89 }
90 }
91}
92
93impl std::fmt::Display for Headers {
94 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
97 write!(f, "{:?}", self)
98 }
99}
100
101fn get_integer_value(header: &reqwest::header::HeaderMap, key: &str) -> Option<u64> {
102 header.get(key)?.to_str().ok()?.parse().ok()
103}
104
105fn get_string_value(header: &reqwest::header::HeaderMap, key: &str) -> Option<String> {
106 header.get(key)?.to_str().ok().map(|it| it.to_string())
107}
108
109fn get_unixtimestamp_value(
110 header: &reqwest::header::HeaderMap,
111 key: &str,
112) -> Option<DateTime<Utc>> {
113 let res = get_integer_value(header, key)?;
114 Utc.timestamp_opt(res as i64, 0).single()
115}