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 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 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 pub fn method(&self) -> Method {
45 self.original_request.method().clone()
46 }
47
48 pub fn base_url(&self) -> &'static str {
50 self.base_url
51 }
52
53 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}