1use std::io;
2
3use std::future::Future;
4use thruster_core::context::Context;
5use thruster_core::request::{Request, RequestWithParams};
6use thruster_core::route_parser::{MatchedRoute, RouteParser};
7use thruster_core::middleware::{MiddlewareChain};
8use thruster_context::basic_context::{generate_context, BasicContext};
9
10enum Method {
11 DELETE,
12 GET,
13 OPTIONS,
14 POST,
15 PUT,
16 UPDATE
17}
18
19fn _add_method_to_route(method: &Method, path: &str) -> String {
21 let prefix = match method {
22 Method::DELETE => "__DELETE__",
23 Method::GET => "__GET__",
24 Method::OPTIONS => "__OPTIONS__",
25 Method::POST => "__POST__",
26 Method::PUT => "__PUT__",
27 Method::UPDATE => "__UPDATE__"
28 };
29
30 match &path[0..1] {
31 "/" => format!("{}{}", prefix, path),
32 _ => format!("{}/{}", prefix, path)
33 }
34}
35
36#[inline]
37fn _add_method_to_route_from_str(method: &str, path: &str) -> String {
38 templatify!("__" ; method ; "__" ; path ; "")
39}
40
41pub struct App<R: RequestWithParams, T: 'static + Context + Send> {
81 pub _route_parser: RouteParser<T>,
82 pub context_generator: fn(R) -> T
88}
89
90impl<R: RequestWithParams, T: Context + Send> App<R, T> {
91 pub fn new_basic() -> App<Request, BasicContext> {
95 App::create(generate_context)
96 }
97
98 pub fn create(generate_context: fn(R) -> T) -> App<R, T> {
101 App {
102 _route_parser: RouteParser::new(),
103 context_generator: generate_context
104 }
105 }
106
107 pub fn use_middleware(&mut self, path: &'static str, middleware: MiddlewareChain<T>) -> &mut App<R, T> {
110 self._route_parser.add_method_agnostic_middleware(path, middleware);
111
112 self
113 }
114
115 pub fn use_sub_app(&mut self, prefix: &'static str, app: App<R, T>) -> &mut App<R, T> {
119 self._route_parser.route_tree
120 .add_route_tree(prefix, app._route_parser.route_tree);
121
122 self
123 }
124
125 pub fn get_route_parser(&self) -> &RouteParser<T> {
127 &self._route_parser
128 }
129
130 pub fn get(&mut self, path: &'static str, middlewares: MiddlewareChain<T>) -> &mut App<R, T> {
132 self._route_parser.add_route(
133 &_add_method_to_route(&Method::GET, path), middlewares);
134
135 self
136 }
137
138 pub fn options(&mut self, path: &'static str, middlewares: MiddlewareChain<T>) -> &mut App<R, T> {
140 self._route_parser.add_route(
141 &_add_method_to_route(&Method::OPTIONS, path), middlewares);
142
143 self
144 }
145
146 pub fn post(&mut self, path: &'static str, middlewares: MiddlewareChain<T>) -> &mut App<R, T> {
148 self._route_parser.add_route(
149 &_add_method_to_route(&Method::POST, path), middlewares);
150
151 self
152 }
153
154 pub fn put(&mut self, path: &'static str, middlewares: MiddlewareChain<T>) -> &mut App<R, T> {
156 self._route_parser.add_route(
157 &_add_method_to_route(&Method::PUT, path), middlewares);
158
159 self
160 }
161
162 pub fn delete(&mut self, path: &'static str, middlewares: MiddlewareChain<T>) -> &mut App<R, T> {
164 self._route_parser.add_route(
165 &_add_method_to_route(&Method::DELETE, path), middlewares);
166
167 self
168 }
169
170 pub fn update(&mut self, path: &'static str, middlewares: MiddlewareChain<T>) -> &mut App<R, T> {
172 self._route_parser.add_route(
173 &_add_method_to_route(&Method::UPDATE, path), middlewares);
174
175 self
176 }
177
178 pub fn set404(&mut self, middlewares: MiddlewareChain<T>) -> &mut App<R, T> {
180 self._route_parser.add_route(
181 &_add_method_to_route(&Method::GET, "/*"), middlewares.clone());
182 self._route_parser.add_route(
183 &_add_method_to_route(&Method::POST, "/*"), middlewares.clone());
184 self._route_parser.add_route(
185 &_add_method_to_route(&Method::PUT, "/*"), middlewares.clone());
186 self._route_parser.add_route(
187 &_add_method_to_route(&Method::UPDATE, "/*"), middlewares.clone());
188 self._route_parser.add_route(
189 &_add_method_to_route(&Method::DELETE, "/*"), middlewares);
190
191 self
192 }
193
194 pub fn resolve_from_method_and_path(&self, method: &str, path: &str) -> MatchedRoute<T> {
195 let path_with_method = &_add_method_to_route_from_str(method, path);
196
197 self._route_parser.match_route(path_with_method)
198 }
199
200 #[cfg(feature = "hyper_server")]
202 pub fn resolve(&self, request: R, matched_route: MatchedRoute<T>) -> impl Future<Output=Result<T::Response, io::Error>> + Send {
203 self._resolve(request, matched_route)
204 }
205
206 #[cfg(not(feature = "hyper_server"))]
207 pub fn resolve(&self, request: R, matched_route: MatchedRoute<T>) -> impl Future<Output=Result<T::Response, io::Error>> + Send {
208 self._resolve(request, matched_route)
209 }
210
211 fn _resolve(&self, request: R, matched_route: MatchedRoute<T>) -> impl Future<Output=Result<T::Response, io::Error>> + Send {
212 use thruster_async_await::resolve;
213
214 resolve(self.context_generator, request, matched_route)
215 }
216}