foxtive_ntex/ext/
request.rs1use 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}