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