1pub mod err {
88 #[derive(Debug)]
90 pub enum Error {
91 CapturesMissing,
92 MethodNotSupported,
93 Http(http::Error),
94 Recognizer(reset_recognizer::err::Error),
95 }
96
97 impl std::fmt::Display for Error {
98 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
99 use Error::*;
100 match self {
101 CapturesMissing => "Captures missing".fmt(f),
102 MethodNotSupported => "Method not supported".fmt(f),
103 Http(ref inner) => inner.fmt(f),
104 Recognizer(ref inner) => inner.fmt(f),
105 }
106 }
107 }
108
109 impl std::error::Error for Error {
110 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
111 use Error::*;
112 match self {
113 Http(ref inner) => Some(inner),
114 Recognizer(ref inner) => Some(inner),
115 _ => None,
116 }
117 }
118 }
119
120 pub type Result<T> = std::result::Result<T, Error>;
122
123 impl From<Error> for http::Response<hyper::Body> {
124 fn from(t: Error) -> Self {
125 http::Response::builder().status(500).body(t.to_string().into()).unwrap()
126 }
127 }
128}
129
130use reset_recognizer as recognizer;
131
132use std::collections::HashMap;
133
134use std::pin::Pin;
135use std::sync::Arc;
136
137use futures::{
138 future::{ready, Ready},
139 ready, Future, FutureExt, TryFuture,
140};
141use std::task::{Context, Poll};
142
143pub type Request = http::Request<hyper::Body>;
145
146pub type Response = http::Response<hyper::Body>;
148
149struct MethodMap<T> {
150 options: Option<T>,
151 get: Option<T>,
152 post: Option<T>,
153 put: Option<T>,
154 delete: Option<T>,
155 head: Option<T>,
156 trace: Option<T>,
157 connect: Option<T>,
158 patch: Option<T>,
159 extension: Option<HashMap<http::Method, T>>,
160}
161
162impl<T> MethodMap<T> {
163 fn new() -> Self {
164 Self {
165 options: None,
166 get: None,
167 post: None,
168 put: None,
169 delete: None,
170 head: None,
171 trace: None,
172 connect: None,
173 patch: None,
174 extension: None,
175 }
176 }
177
178 fn get(&self, method: &http::Method) -> Option<&T> {
179 match *method {
180 http::Method::OPTIONS => self.options.as_ref(),
181 http::Method::GET => self.get.as_ref(),
182 http::Method::POST => self.post.as_ref(),
183 http::Method::PUT => self.put.as_ref(),
184 http::Method::DELETE => self.delete.as_ref(),
185 http::Method::HEAD => self.head.as_ref(),
186 http::Method::TRACE => self.trace.as_ref(),
187 http::Method::CONNECT => self.connect.as_ref(),
188 http::Method::PATCH => self.patch.as_ref(),
189 ref m => self.extension.as_ref().and_then(|e| e.get(m)),
190 }
191 }
192
193 fn insert(&mut self, method: http::Method, t: T) {
194 match method {
195 http::Method::OPTIONS => {
196 self.options = Some(t);
197 }
198 http::Method::GET => {
199 self.get = Some(t);
200 }
201 http::Method::POST => {
202 self.post = Some(t);
203 }
204 http::Method::PUT => {
205 self.put = Some(t);
206 }
207 http::Method::DELETE => {
208 self.delete = Some(t);
209 }
210 http::Method::HEAD => {
211 self.head = Some(t);
212 }
213 http::Method::TRACE => {
214 self.trace = Some(t);
215 }
216 http::Method::CONNECT => {
217 self.connect = Some(t);
218 }
219 http::Method::PATCH => {
220 self.patch = Some(t);
221 }
222 m => {
223 let mut extension = self.extension.take().unwrap_or_else(HashMap::new);
224 extension.insert(m, t);
225 self.extension = Some(extension);
226 }
227 }
228 }
229}
230
231pub struct Data<T>(Arc<T>);
233
234impl<T> Data<T> {
235 pub fn new(t: T) -> Self {
237 Data(Arc::new(t))
238 }
239
240 pub fn from_arc(arc: Arc<T>) -> Self {
242 Data(arc)
243 }
244}
245
246impl<T> std::ops::Deref for Data<T> {
247 type Target = T;
248
249 fn deref(&self) -> &Self::Target {
250 &*self.0
251 }
252}
253
254impl<T> Clone for Data<T> {
255 fn clone(&self) -> Self {
256 Data(Arc::clone(&self.0))
257 }
258}
259
260pub trait SharedService {
270 type Response: Into<Response>;
271 type Error: Into<Box<dyn std::error::Error + Send + Sync + 'static>>;
272 type Future: Future<Output = Result<Self::Response, Self::Error>> + Send;
273
274 fn call(&self, request: Request) -> Self::Future;
275}
276
277#[doc(hidden)]
278#[pin_project::pin_project]
279pub struct HandlerFuture<F> {
280 #[pin]
281 inner: F,
282}
283
284impl<F, S, E> Future for HandlerFuture<F>
285where
286 F: Future<Output = Result<S, E>> + Send,
287 S: Into<Response>,
288 E: Into<Response>,
289{
290 type Output = Result<Response, Box<dyn std::error::Error + Send + Sync + 'static>>;
291
292 #[inline]
293 fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
294 let out = match ready!(self.project().inner.try_poll(cx)) {
295 Ok(res) => Ok(res.into()),
296 Err(err) => Ok(err.into()),
297 };
298 Poll::Ready(out)
299 }
300}
301
302impl<H, F, S, E> SharedService for H
303where
304 F: Future<Output = Result<S, E>> + Send,
305 S: Into<Response>,
306 E: Into<Response>,
307 H: Fn(Request) -> F,
308{
309 type Response = Response;
310 type Error = Box<dyn std::error::Error + Send + Sync + 'static>;
311 type Future = HandlerFuture<F>;
312
313 fn call(&self, request: Request) -> Self::Future {
314 HandlerFuture { inner: self(request) }
315 }
316}
317
318struct BoxedSharedService(
319 Arc<
320 dyn Fn(
321 Request,
322 ) -> Pin<
323 Box<
324 dyn Future<
325 Output = Result<
326 Response,
327 Box<dyn std::error::Error + Send + Sync + 'static>,
328 >,
329 > + Send,
330 >,
331 > + Send
332 + Sync,
333 >,
334);
335
336impl BoxedSharedService {
337 fn new<T: SharedService + Send + Sync + 'static>(t: T) -> Self {
338 Self(Arc::new(move |req: Request| {
339 let rt = t.call(req).map(|res| res.map(|s| s.into()).map_err(|e| e.into()));
340 Box::pin(rt)
341 }))
342 }
343}
344
345#[derive(Clone)]
346struct DataMap(Data<type_map::concurrent::TypeMap>);
347
348struct InnerRouter {
349 data: Option<DataMap>,
350 not_found: BoxedSharedService,
351 routers: MethodMap<recognizer::Router<BoxedSharedService>>,
352}
353
354#[derive(Clone)]
356pub struct Router(Arc<InnerRouter>);
357
358impl Router {
359 pub fn build() -> RouterBuilder {
361 RouterBuilder::new()
362 }
363}
364
365pub struct RouterBuilder {
367 data: Option<type_map::concurrent::TypeMap>,
368 not_found: Option<BoxedSharedService>,
369 inner: HashMap<http::Method, recognizer::RouterBuilder<BoxedSharedService>>,
370}
371
372impl RouterBuilder {
373 fn new() -> Self {
374 RouterBuilder { data: None, not_found: None, inner: HashMap::new() }
375 }
376}
377
378impl RouterBuilder {
379 fn default_not_found(_: Request) -> impl Future<Output = Result<Response, Response>> {
380 async { Ok(http::Response::builder().status(404).body("Not Found".into()).unwrap()) }
381 }
382
383 pub fn data<T: Send + Sync + 'static>(self, data: T) -> Self {
385 self.wrapped_data(Data::new(data))
386 }
387
388 pub fn wrapped_data<T: Send + Sync + 'static>(mut self, data: Data<T>) -> Self {
390 let mut map = self.data.take().unwrap_or_else(type_map::concurrent::TypeMap::new);
391 map.insert(data);
392 self.data = Some(map);
393 self
394 }
395
396 pub fn add_not_found<H>(mut self, handler: H) -> Self
398 where
399 H: SharedService + Send + Sync + 'static,
400 {
401 self.not_found = Some(BoxedSharedService::new(handler));
402 self
403 }
404
405 pub fn add<H>(self, method: http::Method, regex: &str, handler: H) -> Self
407 where
408 H: SharedService + Send + Sync + 'static,
409 {
410 self.add_with_priority(method, regex, 0, handler)
411 }
412
413 pub fn add_with_priority<H>(
415 mut self,
416 method: http::Method,
417 regex: &str,
418 priority: i8,
419 handler: H,
420 ) -> Self
421 where
422 H: SharedService + Send + Sync + 'static,
423 {
424 let handler = BoxedSharedService::new(handler);
425 let entry = self
426 .inner
427 .remove(&method)
428 .unwrap_or_else(recognizer::Router::build)
429 .add_with_priority(regex, priority, handler);
430 self.inner.insert(method, entry);
431
432 self
433 }
434
435 pub fn finish(self) -> err::Result<Router> {
437 let mut inner_router = InnerRouter {
438 data: self.data.map(Data::new).map(DataMap),
439 not_found: self
440 .not_found
441 .unwrap_or_else(|| BoxedSharedService::new(Self::default_not_found)),
442 routers: MethodMap::new(),
443 };
444
445 for (method, builder) in self.inner {
446 let router = builder.finish().map_err(err::Error::Recognizer)?;
447 inner_router.routers.insert(method, router);
448 }
449
450 Ok(Router(Arc::new(inner_router)))
451 }
452}
453
454impl tower::Service<Request> for Router {
455 type Response = Response;
456 type Error = Box<dyn std::error::Error + Send + Sync + 'static>;
457 type Future =
458 std::pin::Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>;
459
460 fn poll_ready(
461 &mut self,
462 _cx: &mut std::task::Context<'_>,
463 ) -> std::task::Poll<Result<(), Self::Error>> {
464 std::task::Poll::Ready(Ok(()))
465 }
466
467 fn call(&mut self, mut request: Request) -> Self::Future {
468 let service = Arc::clone(&self.0);
469
470 if let Some(router) = service.routers.get(request.method()) {
471 if let Ok(recognizer::Match { handler, captures }) =
472 router.recognize(request.uri().path())
473 {
474 let extensions_mut = request.extensions_mut();
475
476 if let Some(ref data) = self.0.data {
477 extensions_mut.insert(data.clone());
478 }
479
480 extensions_mut.insert(captures);
481
482 return handler.0(request);
483 }
484 }
485
486 if let Some(ref data) = self.0.data {
487 request.extensions_mut().insert(data.clone());
488 }
489
490 service.not_found.0(request)
491 }
492}
493
494impl<'a> tower::Service<&'a hyper::server::conn::AddrStream> for Router {
495 type Response = Router;
496 type Error = Box<dyn std::error::Error + Send + Sync + 'static>;
497 type Future = Ready<Result<Self::Response, Self::Error>>;
498
499 fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
500 Poll::Ready(Ok(()))
501 }
502
503 fn call(&mut self, _: &'a hyper::server::conn::AddrStream) -> Self::Future {
504 ready(Ok(Router(Arc::clone(&self.0))))
505 }
506}
507
508pub trait RequestExtensions {
510 fn captures(&self) -> Option<&recognizer::Captures>;
512 fn parsed_captures<C: recognizer::FromCaptures>(&self) -> err::Result<C> {
514 let captures = self.captures().ok_or_else(|| err::Error::CapturesMissing)?;
515 Ok(C::from_captures(&*captures).map_err(err::Error::Recognizer)?)
516 }
517 fn data<T: Send + Sync + 'static>(&self) -> Option<Data<T>>;
519}
520
521impl RequestExtensions for Request {
522 fn captures(&self) -> Option<&recognizer::Captures> {
523 self.extensions().get::<recognizer::Captures>()
524 }
525
526 fn data<T: Send + Sync + 'static>(&self) -> Option<Data<T>> {
527 self.extensions().get::<DataMap>().and_then(|x| x.0.get::<Data<T>>()).cloned()
528 }
529}
530
531impl RequestExtensions for http::request::Parts {
532 fn captures(&self) -> Option<&recognizer::Captures> {
533 self.extensions.get::<recognizer::Captures>()
534 }
535
536 fn data<T: Send + Sync + 'static>(&self) -> Option<Data<T>> {
537 self.extensions.get::<DataMap>().and_then(|x| x.0.get::<Data<T>>()).cloned()
538 }
539}