rs_express/
request.rs

1use hyper::{http::uri::PathAndQuery, Body, Method};
2
3pub struct Request<'a, T> {
4    base_url: &'static str,
5    app_locals: &'a Option<T>,
6    original_request: hyper::Request<Body>,
7}
8
9impl<'a, T> Request<'a, T> {
10    fn new(original_request: hyper::Request<Body>) -> Request<'a, T> {
11        Request {
12            base_url: "/",
13            original_request,
14            app_locals: &None,
15        }
16    }
17
18    pub(crate) fn with_app_locals(&mut self, app_locals: &'a Option<T>) {
19        self.app_locals = app_locals;
20    }
21
22    pub(crate) fn set_base_url(&mut self, base_url: &'static str) {
23        self.base_url = base_url;
24    }
25
26    /// Retrieves the app locals
27    pub fn app_locals(&self) -> Option<&'a T> {
28        match self.app_locals {
29            Some(ref x) => Some(x),
30            None => None,
31        }
32    }
33
34    /// Retrieves the given header value.
35    /// If the header is not present, None will be returned.
36    pub fn header(&self, header: &str) -> Option<String> {
37        self.original_request
38            .headers()
39            .get(header)
40            .map(|header_value| String::from(header_value.to_str().unwrap()))
41    }
42
43    /// Retrieves the request method.
44    pub fn method(&self) -> Method {
45        self.original_request.method().clone()
46    }
47
48    /// Retrieves the base (router) url
49    pub fn base_url(&self) -> &'static str {
50        self.base_url
51    }
52
53    /// Retrieves the full request original url path and query.
54    pub fn original_url(&self) -> PathAndQuery {
55        self.original_request
56            .uri()
57            .path_and_query()
58            .unwrap()
59            .clone()
60    }
61}
62
63impl<'a, T> From<hyper::Request<Body>> for Request<'a, T> {
64    fn from(req: hyper::Request<Body>) -> Self {
65        Request::new(req)
66    }
67}
68
69#[cfg(test)]
70mod tests {
71    use super::*;
72    use std::str::FromStr;
73
74    #[test]
75    fn test_header() {
76        let request = hyper::Request::builder()
77            .header("header-name", "header-value")
78            .body(Body::from("something"))
79            .expect("Failed to create request");
80
81        let req: Request<()> = Request::from(request);
82
83        assert_eq!(req.header("header-name"), Some("header-value".to_string()));
84        assert_eq!(req.header("non-existing-header-name"), None);
85    }
86
87    #[test]
88    fn test_method() {
89        let request = hyper::Request::builder()
90            .method("PUT")
91            .body(Body::from("something"))
92            .expect("Failed to create request");
93
94        let req: Request<()> = Request::from(request);
95
96        assert_eq!(req.method(), Method::PUT);
97    }
98
99    #[test]
100    fn test_original_url() {
101        let request = hyper::Request::builder()
102            .uri("https://localhost:3000/a/b/c?d=1")
103            .body(Body::from("something"))
104            .expect("Failed to create request");
105
106        let req: Request<()> = Request::from(request);
107
108        assert_eq!(
109            req.original_url().as_str(),
110            PathAndQuery::from_str("/a/b/c?d=1").unwrap().as_str()
111        );
112    }
113
114    #[test]
115    fn test_default_base_url() {
116        let request = hyper::Request::builder()
117            .body(Body::from("something"))
118            .expect("Failed to create request");
119
120        let req: Request<()> = Request::from(request);
121
122        assert_eq!(req.base_url(), "/");
123    }
124
125    #[test]
126    fn test_set_base_url() {
127        let request = hyper::Request::builder()
128            .body(Body::from("something"))
129            .expect("Failed to create request");
130
131        let mut req: Request<()> = Request::from(request);
132        req.set_base_url("/base/url");
133
134        assert_eq!(req.base_url(), "/base/url");
135    }
136
137    #[test]
138    fn test_app_locals_none() {
139        let request = hyper::Request::builder()
140            .uri("https://localhost:3000/a/b/c?d=1")
141            .body(Body::from("something"))
142            .expect("Failed to create request");
143
144        let req: Request<()> = Request::from(request);
145
146        assert!(req.app_locals().is_none(),);
147    }
148
149    #[test]
150    fn test_app_locals_some() {
151        #[derive(Clone)]
152        struct Locals {
153            foo: String,
154        }
155
156        let locals = Locals {
157            foo: String::from("hello"),
158        };
159        let app_locals = Some(locals.clone());
160
161        let request = hyper::Request::builder()
162            .uri("https://localhost:3000/a/b/c?d=1")
163            .body(Body::from("something"))
164            .expect("Failed to create request");
165
166        let mut req: Request<Locals> = Request::from(request);
167        req.with_app_locals(&app_locals);
168
169        assert_eq!(req.app_locals().unwrap().foo, locals.foo);
170    }
171}