Skip to main content

foxtive_ntex/ext/
request.rs

1use foxtive::prelude::AppResult;
2use ntex::http::header;
3use ntex::util::Bytes;
4use ntex::web::HttpRequest;
5use serde::de::DeserializeOwned;
6use serde_json::{Map, Value, json};
7use tracing::debug;
8
9use crate::http::extractors::ClientInfo;
10
11#[allow(dead_code)]
12pub trait RequestExt {
13    #[cfg(feature = "database")]
14    fn db_pool(&self) -> &foxtive::database::DBPool;
15
16    fn client_info(&self) -> ClientInfo;
17
18    fn get_headers(&self) -> Map<String, Value>;
19
20    fn json<T: DeserializeOwned>(bytes: Bytes) -> AppResult<T>;
21
22    fn ip(&self) -> Option<String>;
23
24    fn user_agent(&self) -> Option<String>;
25}
26
27impl RequestExt for HttpRequest {
28    #[cfg(feature = "database")]
29    fn db_pool(&self) -> &foxtive::database::DBPool {
30        use foxtive::prelude::AppStateExt;
31        foxtive::FOXTIVE.app().database()
32    }
33
34    fn client_info(&self) -> ClientInfo {
35        ClientInfo {
36            ip: self.ip(),
37            ua: self.user_agent(),
38        }
39    }
40
41    fn get_headers(&self) -> Map<String, Value> {
42        let mut headers_json_object = Map::new();
43
44        for (name, value) in self.headers().iter() {
45            headers_json_object.insert(name.to_string(), json!(value.to_str().unwrap()));
46        }
47
48        headers_json_object
49    }
50
51    fn json<T: DeserializeOwned>(bytes: Bytes) -> AppResult<T> {
52        let raw = String::from_utf8(bytes.to_vec())?;
53        debug!("[json-body]: {raw}");
54        Ok(serde_json::from_str::<T>(&raw)?)
55    }
56
57    fn ip(&self) -> Option<String> {
58        self.connection_info()
59            .remote()
60            .map(|v| v.to_string())
61            .or_else(|| self.peer_addr().map(|s| s.to_string()))
62    }
63
64    fn user_agent(&self) -> Option<String> {
65        self.headers()
66            .get(header::USER_AGENT)
67            .map(|ua| ua.to_str().unwrap().to_string())
68    }
69}