1 use scoped_tls::scoped_thread_local;
2 use std::cell::RefCell;
3 use std::mem;
4 use std::net::SocketAddr;
5 
6 use http;
7 use hyper::Body;
8 
9 use crate::Request;
10 
11 scoped_thread_local!(static ROUTE: RefCell<Route>);
12 
set<F, U>(r: &RefCell<Route>, func: F) -> U where F: FnOnce() -> U,13 pub(crate) fn set<F, U>(r: &RefCell<Route>, func: F) -> U
14 where
15     F: FnOnce() -> U,
16 {
17     ROUTE.set(r, func)
18 }
19 
is_set() -> bool20 pub(crate) fn is_set() -> bool {
21     ROUTE.is_set()
22 }
23 
with<F, R>(func: F) -> R where F: FnOnce(&mut Route) -> R,24 pub(crate) fn with<F, R>(func: F) -> R
25 where
26     F: FnOnce(&mut Route) -> R,
27 {
28     ROUTE.with(move |route| func(&mut *route.borrow_mut()))
29 }
30 
31 #[derive(Debug)]
32 pub(crate) struct Route {
33     body: BodyState,
34     remote_addr: Option<SocketAddr>,
35     req: Request,
36     segments_index: usize,
37 }
38 
39 #[derive(Debug)]
40 enum BodyState {
41     Ready,
42     Taken,
43 }
44 
45 impl Route {
new(req: Request, remote_addr: Option<SocketAddr>) -> RefCell<Route>46     pub(crate) fn new(req: Request, remote_addr: Option<SocketAddr>) -> RefCell<Route> {
47         let segments_index = if req.uri().path().starts_with('/') {
48             // Skip the beginning slash.
49             1
50         } else {
51             0
52         };
53 
54         RefCell::new(Route {
55             body: BodyState::Ready,
56             remote_addr,
57             req,
58             segments_index,
59         })
60     }
61 
method(&self) -> &http::Method62     pub(crate) fn method(&self) -> &http::Method {
63         self.req.method()
64     }
65 
headers(&self) -> &http::HeaderMap66     pub(crate) fn headers(&self) -> &http::HeaderMap {
67         self.req.headers()
68     }
69 
version(&self) -> http::Version70     pub(crate) fn version(&self) -> http::Version {
71         self.req.version()
72     }
73 
extensions(&self) -> &http::Extensions74     pub(crate) fn extensions(&self) -> &http::Extensions {
75         self.req.extensions()
76     }
77 
78     #[cfg(feature = "websocket")]
extensions_mut(&mut self) -> &mut http::Extensions79     pub(crate) fn extensions_mut(&mut self) -> &mut http::Extensions {
80         self.req.extensions_mut()
81     }
82 
uri(&self) -> &http::Uri83     pub(crate) fn uri(&self) -> &http::Uri {
84         self.req.uri()
85     }
86 
path(&self) -> &str87     pub(crate) fn path(&self) -> &str {
88         &self.req.uri().path()[self.segments_index..]
89     }
90 
full_path(&self) -> &str91     pub(crate) fn full_path(&self) -> &str {
92         self.req.uri().path()
93     }
94 
set_unmatched_path(&mut self, index: usize)95     pub(crate) fn set_unmatched_path(&mut self, index: usize) {
96         let index = self.segments_index + index;
97         let path = self.req.uri().path();
98         if path.is_empty() {
99             // malformed path
100             return;
101         } else if path.len() == index {
102             self.segments_index = index;
103         } else {
104             debug_assert_eq!(path.as_bytes()[index], b'/');
105             self.segments_index = index + 1;
106         }
107     }
108 
query(&self) -> Option<&str>109     pub(crate) fn query(&self) -> Option<&str> {
110         self.req.uri().query()
111     }
112 
matched_path_index(&self) -> usize113     pub(crate) fn matched_path_index(&self) -> usize {
114         self.segments_index
115     }
116 
reset_matched_path_index(&mut self, index: usize)117     pub(crate) fn reset_matched_path_index(&mut self, index: usize) {
118         debug_assert!(
119             index <= self.segments_index,
120             "reset_match_path_index should not be bigger: current={}, arg={}",
121             self.segments_index,
122             index,
123         );
124         self.segments_index = index;
125     }
126 
remote_addr(&self) -> Option<SocketAddr>127     pub(crate) fn remote_addr(&self) -> Option<SocketAddr> {
128         self.remote_addr
129     }
130 
take_body(&mut self) -> Option<Body>131     pub(crate) fn take_body(&mut self) -> Option<Body> {
132         match self.body {
133             BodyState::Ready => {
134                 let body = mem::replace(self.req.body_mut(), Body::empty());
135                 self.body = BodyState::Taken;
136                 Some(body)
137             }
138             BodyState::Taken => None,
139         }
140     }
141 }
142