1use self::{future::RouteFuture, not_found::NotFound, path_router::PathRouter};
4#[cfg(feature = "tokio")]
5use crate::extract::connect_info::IntoMakeServiceWithConnectInfo;
6use crate::{
7 body::{Body, HttpBody},
8 boxed::BoxedIntoRoute,
9 handler::Handler,
10 util::try_downcast,
11};
12use axum_core::{
13 extract::Request,
14 response::{IntoResponse, Response},
15};
16use std::{
17 convert::Infallible,
18 fmt,
19 marker::PhantomData,
20 sync::Arc,
21 task::{Context, Poll},
22};
23use tower_layer::Layer;
24use tower_service::Service;
25
26pub mod future;
27pub mod method_routing;
28
29mod into_make_service;
30mod method_filter;
31mod not_found;
32pub(crate) mod path_router;
33mod route;
34mod strip_prefix;
35pub(crate) mod url_params;
36
37#[cfg(test)]
38mod tests;
39
40pub use self::{into_make_service::IntoMakeService, method_filter::MethodFilter, route::Route};
41
42pub use self::method_routing::{
43 any, any_service, connect, connect_service, delete, delete_service, get, get_service, head,
44 head_service, on, on_service, options, options_service, patch, patch_service, post,
45 post_service, put, put_service, trace, trace_service, MethodRouter,
46};
47
48macro_rules! panic_on_err {
49 ($expr:expr) => {
50 match $expr {
51 Ok(x) => x,
52 Err(err) => panic!("{err}"),
53 }
54 };
55}
56
57#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
58pub(crate) struct RouteId(u32);
59
60#[must_use]
68pub struct Router<S = ()> {
69 inner: Arc<RouterInner<S>>,
70}
71
72impl<S> Clone for Router<S> {
73 fn clone(&self) -> Self {
74 Self {
75 inner: Arc::clone(&self.inner),
76 }
77 }
78}
79
80struct RouterInner<S> {
81 path_router: PathRouter<S, false>,
82 fallback_router: PathRouter<S, true>,
83 default_fallback: bool,
84 catch_all_fallback: Fallback<S>,
85}
86
87impl<S> Default for Router<S>
88where
89 S: Clone + Send + Sync + 'static,
90{
91 fn default() -> Self {
92 Self::new()
93 }
94}
95
96impl<S> fmt::Debug for Router<S> {
97 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98 f.debug_struct("Router")
99 .field("path_router", &self.inner.path_router)
100 .field("fallback_router", &self.inner.fallback_router)
101 .field("default_fallback", &self.inner.default_fallback)
102 .field("catch_all_fallback", &self.inner.catch_all_fallback)
103 .finish()
104 }
105}
106
107pub(crate) const NEST_TAIL_PARAM: &str = "__private__axum_nest_tail_param";
108#[cfg(feature = "matched-path")]
109pub(crate) const NEST_TAIL_PARAM_CAPTURE: &str = "/{*__private__axum_nest_tail_param}";
110pub(crate) const FALLBACK_PARAM: &str = "__private__axum_fallback";
111pub(crate) const FALLBACK_PARAM_PATH: &str = "/{*__private__axum_fallback}";
112
113macro_rules! map_inner {
114 ( $self_:ident, $inner:pat_param => $expr:expr) => {
115 #[allow(redundant_semicolons)]
116 {
117 let $inner = $self_.into_inner();
118 Router {
119 inner: Arc::new($expr),
120 }
121 }
122 };
123}
124
125macro_rules! tap_inner {
126 ( $self_:ident, mut $inner:ident => { $($stmt:stmt)* } ) => {
127 #[allow(redundant_semicolons)]
128 {
129 let mut $inner = $self_.into_inner();
130 $($stmt)*;
131 Router {
132 inner: Arc::new($inner),
133 }
134 }
135 };
136}
137
138impl<S> Router<S>
139where
140 S: Clone + Send + Sync + 'static,
141{
142 pub fn new() -> Self {
147 Self {
148 inner: Arc::new(RouterInner {
149 path_router: Default::default(),
150 fallback_router: PathRouter::new_fallback(),
151 default_fallback: true,
152 catch_all_fallback: Fallback::Default(Route::new(NotFound)),
153 }),
154 }
155 }
156
157 fn into_inner(self) -> RouterInner<S> {
158 match Arc::try_unwrap(self.inner) {
159 Ok(inner) => inner,
160 Err(arc) => RouterInner {
161 path_router: arc.path_router.clone(),
162 fallback_router: arc.fallback_router.clone(),
163 default_fallback: arc.default_fallback,
164 catch_all_fallback: arc.catch_all_fallback.clone(),
165 },
166 }
167 }
168
169 #[doc = include_str!("../docs/routing/without_v07_checks.md")]
170 pub fn without_v07_checks(self) -> Self {
171 tap_inner!(self, mut this => {
172 this.path_router.without_v07_checks();
173 })
174 }
175
176 #[doc = include_str!("../docs/routing/route.md")]
177 #[track_caller]
178 pub fn route(self, path: &str, method_router: MethodRouter<S>) -> Self {
179 tap_inner!(self, mut this => {
180 panic_on_err!(this.path_router.route(path, method_router));
181 })
182 }
183
184 #[doc = include_str!("../docs/routing/route_service.md")]
185 pub fn route_service<T>(self, path: &str, service: T) -> Self
186 where
187 T: Service<Request, Error = Infallible> + Clone + Send + Sync + 'static,
188 T::Response: IntoResponse,
189 T::Future: Send + 'static,
190 {
191 let service = match try_downcast::<Router<S>, _>(service) {
192 Ok(_) => {
193 panic!(
194 "Invalid route: `Router::route_service` cannot be used with `Router`s. \
195 Use `Router::nest` instead"
196 );
197 }
198 Err(service) => service,
199 };
200
201 tap_inner!(self, mut this => {
202 panic_on_err!(this.path_router.route_service(path, service));
203 })
204 }
205
206 #[doc = include_str!("../docs/routing/nest.md")]
207 #[doc(alias = "scope")] #[track_caller]
209 pub fn nest(self, path: &str, router: Router<S>) -> Self {
210 if path.is_empty() || path == "/" {
211 panic!("Nesting at the root is no longer supported. Use merge instead.");
212 }
213
214 let RouterInner {
215 path_router,
216 fallback_router,
217 default_fallback,
218 catch_all_fallback: _,
222 } = router.into_inner();
223
224 tap_inner!(self, mut this => {
225 panic_on_err!(this.path_router.nest(path, path_router));
226
227 if !default_fallback {
228 panic_on_err!(this.fallback_router.nest(path, fallback_router));
229 }
230 })
231 }
232
233 #[track_caller]
235 pub fn nest_service<T>(self, path: &str, service: T) -> Self
236 where
237 T: Service<Request, Error = Infallible> + Clone + Send + Sync + 'static,
238 T::Response: IntoResponse,
239 T::Future: Send + 'static,
240 {
241 if path.is_empty() || path == "/" {
242 panic!("Nesting at the root is no longer supported. Use fallback_service instead.");
243 }
244
245 tap_inner!(self, mut this => {
246 panic_on_err!(this.path_router.nest_service(path, service));
247 })
248 }
249
250 #[doc = include_str!("../docs/routing/merge.md")]
251 #[track_caller]
252 pub fn merge<R>(self, other: R) -> Self
253 where
254 R: Into<Router<S>>,
255 {
256 const PANIC_MSG: &str =
257 "Failed to merge fallbacks. This is a bug in axum. Please file an issue";
258
259 let other: Router<S> = other.into();
260 let RouterInner {
261 path_router,
262 fallback_router: mut other_fallback,
263 default_fallback,
264 catch_all_fallback,
265 } = other.into_inner();
266
267 map_inner!(self, mut this => {
268 panic_on_err!(this.path_router.merge(path_router));
269
270 match (this.default_fallback, default_fallback) {
271 (true, true) => {
274 this.fallback_router.merge(other_fallback).expect(PANIC_MSG);
275 }
276 (true, false) => {
278 this.fallback_router.merge(other_fallback).expect(PANIC_MSG);
279 this.default_fallback = false;
280 }
281 (false, true) => {
283 let fallback_router = std::mem::take(&mut this.fallback_router);
284 other_fallback.merge(fallback_router).expect(PANIC_MSG);
285 this.fallback_router = other_fallback;
286 }
287 (false, false) => {
289 panic!("Cannot merge two `Router`s that both have a fallback")
290 }
291 };
292
293 this.catch_all_fallback = this
294 .catch_all_fallback
295 .merge(catch_all_fallback)
296 .unwrap_or_else(|| panic!("Cannot merge two `Router`s that both have a fallback"));
297
298 this
299 })
300 }
301
302 #[doc = include_str!("../docs/routing/layer.md")]
303 pub fn layer<L>(self, layer: L) -> Router<S>
304 where
305 L: Layer<Route> + Clone + Send + Sync + 'static,
306 L::Service: Service<Request> + Clone + Send + Sync + 'static,
307 <L::Service as Service<Request>>::Response: IntoResponse + 'static,
308 <L::Service as Service<Request>>::Error: Into<Infallible> + 'static,
309 <L::Service as Service<Request>>::Future: Send + 'static,
310 {
311 map_inner!(self, this => RouterInner {
312 path_router: this.path_router.layer(layer.clone()),
313 fallback_router: this.fallback_router.layer(layer.clone()),
314 default_fallback: this.default_fallback,
315 catch_all_fallback: this.catch_all_fallback.map(|route| route.layer(layer)),
316 })
317 }
318
319 #[doc = include_str!("../docs/routing/route_layer.md")]
320 #[track_caller]
321 pub fn route_layer<L>(self, layer: L) -> Self
322 where
323 L: Layer<Route> + Clone + Send + Sync + 'static,
324 L::Service: Service<Request> + Clone + Send + Sync + 'static,
325 <L::Service as Service<Request>>::Response: IntoResponse + 'static,
326 <L::Service as Service<Request>>::Error: Into<Infallible> + 'static,
327 <L::Service as Service<Request>>::Future: Send + 'static,
328 {
329 map_inner!(self, this => RouterInner {
330 path_router: this.path_router.route_layer(layer),
331 fallback_router: this.fallback_router,
332 default_fallback: this.default_fallback,
333 catch_all_fallback: this.catch_all_fallback,
334 })
335 }
336
337 #[must_use]
339 pub fn has_routes(&self) -> bool {
340 self.inner.path_router.has_routes()
341 }
342
343 #[track_caller]
344 #[doc = include_str!("../docs/routing/fallback.md")]
345 pub fn fallback<H, T>(self, handler: H) -> Self
346 where
347 H: Handler<T, S>,
348 T: 'static,
349 {
350 tap_inner!(self, mut this => {
351 this.catch_all_fallback =
352 Fallback::BoxedHandler(BoxedIntoRoute::from_handler(handler.clone()));
353 })
354 .fallback_endpoint(Endpoint::MethodRouter(any(handler)))
355 }
356
357 pub fn fallback_service<T>(self, service: T) -> Self
361 where
362 T: Service<Request, Error = Infallible> + Clone + Send + Sync + 'static,
363 T::Response: IntoResponse,
364 T::Future: Send + 'static,
365 {
366 let route = Route::new(service);
367 tap_inner!(self, mut this => {
368 this.catch_all_fallback = Fallback::Service(route.clone());
369 })
370 .fallback_endpoint(Endpoint::Route(route))
371 }
372
373 #[doc = include_str!("../docs/routing/method_not_allowed_fallback.md")]
374 pub fn method_not_allowed_fallback<H, T>(self, handler: H) -> Self
375 where
376 H: Handler<T, S>,
377 T: 'static,
378 {
379 tap_inner!(self, mut this => {
380 this.path_router
381 .method_not_allowed_fallback(handler.clone());
382 })
383 }
384
385 pub fn reset_fallback(self) -> Self {
393 tap_inner!(self, mut this => {
394 this.fallback_router = PathRouter::new_fallback();
395 this.default_fallback = true;
396 this.catch_all_fallback = Fallback::Default(Route::new(NotFound));
397 })
398 }
399
400 fn fallback_endpoint(self, endpoint: Endpoint<S>) -> Self {
401 tap_inner!(self, mut this => {
402 this.fallback_router.set_fallback(endpoint);
403 this.default_fallback = false;
404 })
405 }
406
407 #[doc = include_str!("../docs/routing/with_state.md")]
408 pub fn with_state<S2>(self, state: S) -> Router<S2> {
409 map_inner!(self, this => RouterInner {
410 path_router: this.path_router.with_state(state.clone()),
411 fallback_router: this.fallback_router.with_state(state.clone()),
412 default_fallback: this.default_fallback,
413 catch_all_fallback: this.catch_all_fallback.with_state(state),
414 })
415 }
416
417 pub(crate) fn call_with_state(&self, req: Request, state: S) -> RouteFuture<Infallible> {
418 let (req, state) = match self.inner.path_router.call_with_state(req, state) {
419 Ok(future) => return future,
420 Err((req, state)) => (req, state),
421 };
422
423 let (req, state) = match self.inner.fallback_router.call_with_state(req, state) {
424 Ok(future) => return future,
425 Err((req, state)) => (req, state),
426 };
427
428 self.inner
429 .catch_all_fallback
430 .clone()
431 .call_with_state(req, state)
432 }
433
434 pub fn as_service<B>(&mut self) -> RouterAsService<'_, B, S> {
488 RouterAsService {
489 router: self,
490 _marker: PhantomData,
491 }
492 }
493
494 #[must_use]
500 pub fn into_service<B>(self) -> RouterIntoService<B, S> {
501 RouterIntoService {
502 router: self,
503 _marker: PhantomData,
504 }
505 }
506}
507
508impl Router {
509 #[must_use]
528 pub fn into_make_service(self) -> IntoMakeService<Self> {
529 IntoMakeService::new(self.with_state(()))
532 }
533
534 #[doc = include_str!("../docs/routing/into_make_service_with_connect_info.md")]
535 #[cfg(feature = "tokio")]
536 #[must_use]
537 pub fn into_make_service_with_connect_info<C>(self) -> IntoMakeServiceWithConnectInfo<Self, C> {
538 IntoMakeServiceWithConnectInfo::new(self.with_state(()))
541 }
542}
543
544#[cfg(all(feature = "tokio", any(feature = "http1", feature = "http2")))]
546const _: () = {
547 use crate::serve;
548
549 impl<L> Service<serve::IncomingStream<'_, L>> for Router<()>
550 where
551 L: serve::Listener,
552 {
553 type Response = Self;
554 type Error = Infallible;
555 type Future = std::future::Ready<Result<Self::Response, Self::Error>>;
556
557 fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
558 Poll::Ready(Ok(()))
559 }
560
561 fn call(&mut self, _req: serve::IncomingStream<'_, L>) -> Self::Future {
562 std::future::ready(Ok(self.clone().with_state(())))
565 }
566 }
567};
568
569impl<B> Service<Request<B>> for Router<()>
570where
571 B: HttpBody<Data = bytes::Bytes> + Send + 'static,
572 B::Error: Into<axum_core::BoxError>,
573{
574 type Response = Response;
575 type Error = Infallible;
576 type Future = RouteFuture<Infallible>;
577
578 #[inline]
579 fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
580 Poll::Ready(Ok(()))
581 }
582
583 #[inline]
584 fn call(&mut self, req: Request<B>) -> Self::Future {
585 let req = req.map(Body::new);
586 self.call_with_state(req, ())
587 }
588}
589
590pub struct RouterAsService<'a, B, S = ()> {
594 router: &'a mut Router<S>,
595 _marker: PhantomData<fn(B)>,
596}
597
598impl<B> Service<Request<B>> for RouterAsService<'_, B, ()>
599where
600 B: HttpBody<Data = bytes::Bytes> + Send + 'static,
601 B::Error: Into<axum_core::BoxError>,
602{
603 type Response = Response;
604 type Error = Infallible;
605 type Future = RouteFuture<Infallible>;
606
607 #[inline]
608 fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
609 <Router as Service<Request<B>>>::poll_ready(self.router, cx)
610 }
611
612 #[inline]
613 fn call(&mut self, req: Request<B>) -> Self::Future {
614 self.router.call(req)
615 }
616}
617
618impl<B, S> fmt::Debug for RouterAsService<'_, B, S>
619where
620 S: fmt::Debug,
621{
622 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
623 f.debug_struct("RouterAsService")
624 .field("router", &self.router)
625 .finish()
626 }
627}
628
629pub struct RouterIntoService<B, S = ()> {
633 router: Router<S>,
634 _marker: PhantomData<fn(B)>,
635}
636
637impl<B, S> Clone for RouterIntoService<B, S>
638where
639 Router<S>: Clone,
640{
641 fn clone(&self) -> Self {
642 Self {
643 router: self.router.clone(),
644 _marker: PhantomData,
645 }
646 }
647}
648
649impl<B> Service<Request<B>> for RouterIntoService<B, ()>
650where
651 B: HttpBody<Data = bytes::Bytes> + Send + 'static,
652 B::Error: Into<axum_core::BoxError>,
653{
654 type Response = Response;
655 type Error = Infallible;
656 type Future = RouteFuture<Infallible>;
657
658 #[inline]
659 fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
660 <Router as Service<Request<B>>>::poll_ready(&mut self.router, cx)
661 }
662
663 #[inline]
664 fn call(&mut self, req: Request<B>) -> Self::Future {
665 self.router.call(req)
666 }
667}
668
669impl<B, S> fmt::Debug for RouterIntoService<B, S>
670where
671 S: fmt::Debug,
672{
673 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
674 f.debug_struct("RouterIntoService")
675 .field("router", &self.router)
676 .finish()
677 }
678}
679
680enum Fallback<S, E = Infallible> {
681 Default(Route<E>),
682 Service(Route<E>),
683 BoxedHandler(BoxedIntoRoute<S, E>),
684}
685
686impl<S, E> Fallback<S, E>
687where
688 S: Clone,
689{
690 fn merge(self, other: Self) -> Option<Self> {
691 match (self, other) {
692 (Self::Default(_), pick @ Self::Default(_)) => Some(pick),
693 (Self::Default(_), pick) | (pick, Self::Default(_)) => Some(pick),
694 _ => None,
695 }
696 }
697
698 fn map<F, E2>(self, f: F) -> Fallback<S, E2>
699 where
700 S: 'static,
701 E: 'static,
702 F: FnOnce(Route<E>) -> Route<E2> + Clone + Send + Sync + 'static,
703 E2: 'static,
704 {
705 match self {
706 Self::Default(route) => Fallback::Default(f(route)),
707 Self::Service(route) => Fallback::Service(f(route)),
708 Self::BoxedHandler(handler) => Fallback::BoxedHandler(handler.map(f)),
709 }
710 }
711
712 fn with_state<S2>(self, state: S) -> Fallback<S2, E> {
713 match self {
714 Fallback::Default(route) => Fallback::Default(route),
715 Fallback::Service(route) => Fallback::Service(route),
716 Fallback::BoxedHandler(handler) => Fallback::Service(handler.into_route(state)),
717 }
718 }
719
720 fn call_with_state(self, req: Request, state: S) -> RouteFuture<E> {
721 match self {
722 Fallback::Default(route) | Fallback::Service(route) => route.oneshot_inner_owned(req),
723 Fallback::BoxedHandler(handler) => {
724 let route = handler.clone().into_route(state);
725 route.oneshot_inner_owned(req)
726 }
727 }
728 }
729}
730
731impl<S, E> Clone for Fallback<S, E> {
732 fn clone(&self) -> Self {
733 match self {
734 Self::Default(inner) => Self::Default(inner.clone()),
735 Self::Service(inner) => Self::Service(inner.clone()),
736 Self::BoxedHandler(inner) => Self::BoxedHandler(inner.clone()),
737 }
738 }
739}
740
741impl<S, E> fmt::Debug for Fallback<S, E> {
742 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
743 match self {
744 Self::Default(inner) => f.debug_tuple("Default").field(inner).finish(),
745 Self::Service(inner) => f.debug_tuple("Service").field(inner).finish(),
746 Self::BoxedHandler(_) => f.debug_tuple("BoxedHandler").finish(),
747 }
748 }
749}
750
751#[allow(clippy::large_enum_variant)]
752enum Endpoint<S> {
753 MethodRouter(MethodRouter<S>),
754 Route(Route),
755}
756
757impl<S> Endpoint<S>
758where
759 S: Clone + Send + Sync + 'static,
760{
761 fn layer<L>(self, layer: L) -> Endpoint<S>
762 where
763 L: Layer<Route> + Clone + Send + Sync + 'static,
764 L::Service: Service<Request> + Clone + Send + Sync + 'static,
765 <L::Service as Service<Request>>::Response: IntoResponse + 'static,
766 <L::Service as Service<Request>>::Error: Into<Infallible> + 'static,
767 <L::Service as Service<Request>>::Future: Send + 'static,
768 {
769 match self {
770 Endpoint::MethodRouter(method_router) => {
771 Endpoint::MethodRouter(method_router.layer(layer))
772 }
773 Endpoint::Route(route) => Endpoint::Route(route.layer(layer)),
774 }
775 }
776}
777
778impl<S> Clone for Endpoint<S> {
779 fn clone(&self) -> Self {
780 match self {
781 Self::MethodRouter(inner) => Self::MethodRouter(inner.clone()),
782 Self::Route(inner) => Self::Route(inner.clone()),
783 }
784 }
785}
786
787impl<S> fmt::Debug for Endpoint<S> {
788 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
789 match self {
790 Self::MethodRouter(method_router) => {
791 f.debug_tuple("MethodRouter").field(method_router).finish()
792 }
793 Self::Route(route) => f.debug_tuple("Route").field(route).finish(),
794 }
795 }
796}
797
798#[test]
799fn traits() {
800 use crate::test_helpers::*;
801 assert_send::<Router<()>>();
802 assert_sync::<Router<()>>();
803 assert_send::<RouterAsService<'static, Body, ()>>();
804 assert_sync::<RouterAsService<'static, Body, ()>>();
805 assert_send::<RouterIntoService<Body, ()>>();
806 assert_sync::<RouterIntoService<Body, ()>>();
807}