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]
62pub struct Router<S = ()> {
63 inner: Arc<RouterInner<S>>,
64}
65
66impl<S> Clone for Router<S> {
67 fn clone(&self) -> Self {
68 Self {
69 inner: Arc::clone(&self.inner),
70 }
71 }
72}
73
74struct RouterInner<S> {
75 path_router: PathRouter<S, false>,
76 fallback_router: PathRouter<S, true>,
77 default_fallback: bool,
78 catch_all_fallback: Fallback<S>,
79}
80
81impl<S> Default for Router<S>
82where
83 S: Clone + Send + Sync + 'static,
84{
85 fn default() -> Self {
86 Self::new()
87 }
88}
89
90impl<S> fmt::Debug for Router<S> {
91 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
92 f.debug_struct("Router")
93 .field("path_router", &self.inner.path_router)
94 .field("fallback_router", &self.inner.fallback_router)
95 .field("default_fallback", &self.inner.default_fallback)
96 .field("catch_all_fallback", &self.inner.catch_all_fallback)
97 .finish()
98 }
99}
100
101pub(crate) const NEST_TAIL_PARAM: &str = "__private__axum_nest_tail_param";
102#[cfg(feature = "matched-path")]
103pub(crate) const NEST_TAIL_PARAM_CAPTURE: &str = "/{*__private__axum_nest_tail_param}";
104pub(crate) const FALLBACK_PARAM: &str = "__private__axum_fallback";
105pub(crate) const FALLBACK_PARAM_PATH: &str = "/{*__private__axum_fallback}";
106
107macro_rules! map_inner {
108 ( $self_:ident, $inner:pat_param => $expr:expr) => {
109 #[allow(redundant_semicolons)]
110 {
111 let $inner = $self_.into_inner();
112 Router {
113 inner: Arc::new($expr),
114 }
115 }
116 };
117}
118
119macro_rules! tap_inner {
120 ( $self_:ident, mut $inner:ident => { $($stmt:stmt)* } ) => {
121 #[allow(redundant_semicolons)]
122 {
123 let mut $inner = $self_.into_inner();
124 $($stmt)*
125 Router {
126 inner: Arc::new($inner),
127 }
128 }
129 };
130}
131
132impl<S> Router<S>
133where
134 S: Clone + Send + Sync + 'static,
135{
136 pub fn new() -> Self {
141 Self {
142 inner: Arc::new(RouterInner {
143 path_router: Default::default(),
144 fallback_router: PathRouter::new_fallback(),
145 default_fallback: true,
146 catch_all_fallback: Fallback::Default(Route::new(NotFound)),
147 }),
148 }
149 }
150
151 fn into_inner(self) -> RouterInner<S> {
152 match Arc::try_unwrap(self.inner) {
153 Ok(inner) => inner,
154 Err(arc) => RouterInner {
155 path_router: arc.path_router.clone(),
156 fallback_router: arc.fallback_router.clone(),
157 default_fallback: arc.default_fallback,
158 catch_all_fallback: arc.catch_all_fallback.clone(),
159 },
160 }
161 }
162
163 #[doc = include_str!("../docs/routing/without_v07_checks.md")]
164 pub fn without_v07_checks(self) -> Self {
165 tap_inner!(self, mut this => {
166 this.path_router.without_v07_checks();
167 })
168 }
169
170 #[doc = include_str!("../docs/routing/route.md")]
171 #[track_caller]
172 pub fn route(self, path: &str, method_router: MethodRouter<S>) -> Self {
173 tap_inner!(self, mut this => {
174 panic_on_err!(this.path_router.route(path, method_router));
175 })
176 }
177
178 #[doc = include_str!("../docs/routing/route_service.md")]
179 pub fn route_service<T>(self, path: &str, service: T) -> Self
180 where
181 T: Service<Request, Error = Infallible> + Clone + Send + Sync + 'static,
182 T::Response: IntoResponse,
183 T::Future: Send + 'static,
184 {
185 let service = match try_downcast::<Router<S>, _>(service) {
186 Ok(_) => {
187 panic!(
188 "Invalid route: `Router::route_service` cannot be used with `Router`s. \
189 Use `Router::nest` instead"
190 );
191 }
192 Err(service) => service,
193 };
194
195 tap_inner!(self, mut this => {
196 panic_on_err!(this.path_router.route_service(path, service));
197 })
198 }
199
200 #[doc = include_str!("../docs/routing/nest.md")]
201 #[doc(alias = "scope")] #[track_caller]
203 pub fn nest(self, path: &str, router: Router<S>) -> Self {
204 if path.is_empty() || path == "/" {
205 panic!("Nesting at the root is no longer supported. Use merge instead.");
206 }
207
208 let RouterInner {
209 path_router,
210 fallback_router,
211 default_fallback,
212 catch_all_fallback: _,
216 } = router.into_inner();
217
218 tap_inner!(self, mut this => {
219 panic_on_err!(this.path_router.nest(path, path_router));
220
221 if !default_fallback {
222 panic_on_err!(this.fallback_router.nest(path, fallback_router));
223 }
224 })
225 }
226
227 #[track_caller]
229 pub fn nest_service<T>(self, path: &str, service: T) -> Self
230 where
231 T: Service<Request, Error = Infallible> + Clone + Send + Sync + 'static,
232 T::Response: IntoResponse,
233 T::Future: Send + 'static,
234 {
235 if path.is_empty() || path == "/" {
236 panic!("Nesting at the root is no longer supported. Use fallback_service instead.");
237 }
238
239 tap_inner!(self, mut this => {
240 panic_on_err!(this.path_router.nest_service(path, service));
241 })
242 }
243
244 #[doc = include_str!("../docs/routing/merge.md")]
245 #[track_caller]
246 pub fn merge<R>(self, other: R) -> Self
247 where
248 R: Into<Router<S>>,
249 {
250 const PANIC_MSG: &str =
251 "Failed to merge fallbacks. This is a bug in axum. Please file an issue";
252
253 let other: Router<S> = other.into();
254 let RouterInner {
255 path_router,
256 fallback_router: mut other_fallback,
257 default_fallback,
258 catch_all_fallback,
259 } = other.into_inner();
260
261 map_inner!(self, mut this => {
262 panic_on_err!(this.path_router.merge(path_router));
263
264 match (this.default_fallback, default_fallback) {
265 (true, true) => {
268 this.fallback_router.merge(other_fallback).expect(PANIC_MSG);
269 }
270 (true, false) => {
272 this.fallback_router.merge(other_fallback).expect(PANIC_MSG);
273 this.default_fallback = false;
274 }
275 (false, true) => {
277 let fallback_router = std::mem::take(&mut this.fallback_router);
278 other_fallback.merge(fallback_router).expect(PANIC_MSG);
279 this.fallback_router = other_fallback;
280 }
281 (false, false) => {
283 panic!("Cannot merge two `Router`s that both have a fallback")
284 }
285 };
286
287 this.catch_all_fallback = this
288 .catch_all_fallback
289 .merge(catch_all_fallback)
290 .unwrap_or_else(|| panic!("Cannot merge two `Router`s that both have a fallback"));
291
292 this
293 })
294 }
295
296 #[doc = include_str!("../docs/routing/layer.md")]
297 pub fn layer<L>(self, layer: L) -> Router<S>
298 where
299 L: Layer<Route> + Clone + Send + Sync + 'static,
300 L::Service: Service<Request> + Clone + Send + Sync + 'static,
301 <L::Service as Service<Request>>::Response: IntoResponse + 'static,
302 <L::Service as Service<Request>>::Error: Into<Infallible> + 'static,
303 <L::Service as Service<Request>>::Future: Send + 'static,
304 {
305 map_inner!(self, this => RouterInner {
306 path_router: this.path_router.layer(layer.clone()),
307 fallback_router: this.fallback_router.layer(layer.clone()),
308 default_fallback: this.default_fallback,
309 catch_all_fallback: this.catch_all_fallback.map(|route| route.layer(layer)),
310 })
311 }
312
313 #[doc = include_str!("../docs/routing/route_layer.md")]
314 #[track_caller]
315 pub fn route_layer<L>(self, layer: L) -> Self
316 where
317 L: Layer<Route> + Clone + Send + Sync + 'static,
318 L::Service: Service<Request> + Clone + Send + Sync + 'static,
319 <L::Service as Service<Request>>::Response: IntoResponse + 'static,
320 <L::Service as Service<Request>>::Error: Into<Infallible> + 'static,
321 <L::Service as Service<Request>>::Future: Send + 'static,
322 {
323 map_inner!(self, this => RouterInner {
324 path_router: this.path_router.route_layer(layer),
325 fallback_router: this.fallback_router,
326 default_fallback: this.default_fallback,
327 catch_all_fallback: this.catch_all_fallback,
328 })
329 }
330
331 pub fn has_routes(&self) -> bool {
333 self.inner.path_router.has_routes()
334 }
335
336 #[track_caller]
337 #[doc = include_str!("../docs/routing/fallback.md")]
338 pub fn fallback<H, T>(self, handler: H) -> Self
339 where
340 H: Handler<T, S>,
341 T: 'static,
342 {
343 tap_inner!(self, mut this => {
344 this.catch_all_fallback =
345 Fallback::BoxedHandler(BoxedIntoRoute::from_handler(handler.clone()));
346 })
347 .fallback_endpoint(Endpoint::MethodRouter(any(handler)))
348 }
349
350 pub fn fallback_service<T>(self, service: T) -> Self
354 where
355 T: Service<Request, Error = Infallible> + Clone + Send + Sync + 'static,
356 T::Response: IntoResponse,
357 T::Future: Send + 'static,
358 {
359 let route = Route::new(service);
360 tap_inner!(self, mut this => {
361 this.catch_all_fallback = Fallback::Service(route.clone());
362 })
363 .fallback_endpoint(Endpoint::Route(route))
364 }
365
366 #[doc = include_str!("../docs/routing/method_not_allowed_fallback.md")]
367 pub fn method_not_allowed_fallback<H, T>(self, handler: H) -> Self
368 where
369 H: Handler<T, S>,
370 T: 'static,
371 {
372 tap_inner!(self, mut this => {
373 this.path_router
374 .method_not_allowed_fallback(handler.clone())
375 })
376 }
377
378 fn fallback_endpoint(self, endpoint: Endpoint<S>) -> Self {
379 tap_inner!(self, mut this => {
380 this.fallback_router.set_fallback(endpoint);
381 this.default_fallback = false;
382 })
383 }
384
385 #[doc = include_str!("../docs/routing/with_state.md")]
386 pub fn with_state<S2>(self, state: S) -> Router<S2> {
387 map_inner!(self, this => RouterInner {
388 path_router: this.path_router.with_state(state.clone()),
389 fallback_router: this.fallback_router.with_state(state.clone()),
390 default_fallback: this.default_fallback,
391 catch_all_fallback: this.catch_all_fallback.with_state(state),
392 })
393 }
394
395 pub(crate) fn call_with_state(&self, req: Request, state: S) -> RouteFuture<Infallible> {
396 let (req, state) = match self.inner.path_router.call_with_state(req, state) {
397 Ok(future) => return future,
398 Err((req, state)) => (req, state),
399 };
400
401 let (req, state) = match self.inner.fallback_router.call_with_state(req, state) {
402 Ok(future) => return future,
403 Err((req, state)) => (req, state),
404 };
405
406 self.inner
407 .catch_all_fallback
408 .clone()
409 .call_with_state(req, state)
410 }
411
412 pub fn as_service<B>(&mut self) -> RouterAsService<'_, B, S> {
466 RouterAsService {
467 router: self,
468 _marker: PhantomData,
469 }
470 }
471
472 pub fn into_service<B>(self) -> RouterIntoService<B, S> {
478 RouterIntoService {
479 router: self,
480 _marker: PhantomData,
481 }
482 }
483}
484
485impl Router {
486 pub fn into_make_service(self) -> IntoMakeService<Self> {
505 IntoMakeService::new(self.with_state(()))
508 }
509
510 #[doc = include_str!("../docs/routing/into_make_service_with_connect_info.md")]
511 #[cfg(feature = "tokio")]
512 pub fn into_make_service_with_connect_info<C>(self) -> IntoMakeServiceWithConnectInfo<Self, C> {
513 IntoMakeServiceWithConnectInfo::new(self.with_state(()))
516 }
517}
518
519#[cfg(all(feature = "tokio", any(feature = "http1", feature = "http2")))]
521const _: () = {
522 use crate::serve;
523
524 impl<L> Service<serve::IncomingStream<'_, L>> for Router<()>
525 where
526 L: serve::Listener,
527 {
528 type Response = Self;
529 type Error = Infallible;
530 type Future = std::future::Ready<Result<Self::Response, Self::Error>>;
531
532 fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
533 Poll::Ready(Ok(()))
534 }
535
536 fn call(&mut self, _req: serve::IncomingStream<'_, L>) -> Self::Future {
537 std::future::ready(Ok(self.clone().with_state(())))
540 }
541 }
542};
543
544impl<B> Service<Request<B>> for Router<()>
545where
546 B: HttpBody<Data = bytes::Bytes> + Send + 'static,
547 B::Error: Into<axum_core::BoxError>,
548{
549 type Response = Response;
550 type Error = Infallible;
551 type Future = RouteFuture<Infallible>;
552
553 #[inline]
554 fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
555 Poll::Ready(Ok(()))
556 }
557
558 #[inline]
559 fn call(&mut self, req: Request<B>) -> Self::Future {
560 let req = req.map(Body::new);
561 self.call_with_state(req, ())
562 }
563}
564
565pub struct RouterAsService<'a, B, S = ()> {
569 router: &'a mut Router<S>,
570 _marker: PhantomData<B>,
571}
572
573impl<B> Service<Request<B>> for RouterAsService<'_, B, ()>
574where
575 B: HttpBody<Data = bytes::Bytes> + Send + 'static,
576 B::Error: Into<axum_core::BoxError>,
577{
578 type Response = Response;
579 type Error = Infallible;
580 type Future = RouteFuture<Infallible>;
581
582 #[inline]
583 fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
584 <Router as Service<Request<B>>>::poll_ready(self.router, cx)
585 }
586
587 #[inline]
588 fn call(&mut self, req: Request<B>) -> Self::Future {
589 self.router.call(req)
590 }
591}
592
593impl<B, S> fmt::Debug for RouterAsService<'_, B, S>
594where
595 S: fmt::Debug,
596{
597 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
598 f.debug_struct("RouterAsService")
599 .field("router", &self.router)
600 .finish()
601 }
602}
603
604pub struct RouterIntoService<B, S = ()> {
608 router: Router<S>,
609 _marker: PhantomData<B>,
610}
611
612impl<B, S> Clone for RouterIntoService<B, S>
613where
614 Router<S>: Clone,
615{
616 fn clone(&self) -> Self {
617 Self {
618 router: self.router.clone(),
619 _marker: PhantomData,
620 }
621 }
622}
623
624impl<B> Service<Request<B>> for RouterIntoService<B, ()>
625where
626 B: HttpBody<Data = bytes::Bytes> + Send + 'static,
627 B::Error: Into<axum_core::BoxError>,
628{
629 type Response = Response;
630 type Error = Infallible;
631 type Future = RouteFuture<Infallible>;
632
633 #[inline]
634 fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
635 <Router as Service<Request<B>>>::poll_ready(&mut self.router, cx)
636 }
637
638 #[inline]
639 fn call(&mut self, req: Request<B>) -> Self::Future {
640 self.router.call(req)
641 }
642}
643
644impl<B, S> fmt::Debug for RouterIntoService<B, S>
645where
646 S: fmt::Debug,
647{
648 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
649 f.debug_struct("RouterIntoService")
650 .field("router", &self.router)
651 .finish()
652 }
653}
654
655enum Fallback<S, E = Infallible> {
656 Default(Route<E>),
657 Service(Route<E>),
658 BoxedHandler(BoxedIntoRoute<S, E>),
659}
660
661impl<S, E> Fallback<S, E>
662where
663 S: Clone,
664{
665 fn merge(self, other: Self) -> Option<Self> {
666 match (self, other) {
667 (Self::Default(_), pick @ Self::Default(_)) => Some(pick),
668 (Self::Default(_), pick) | (pick, Self::Default(_)) => Some(pick),
669 _ => None,
670 }
671 }
672
673 fn map<F, E2>(self, f: F) -> Fallback<S, E2>
674 where
675 S: 'static,
676 E: 'static,
677 F: FnOnce(Route<E>) -> Route<E2> + Clone + Send + Sync + 'static,
678 E2: 'static,
679 {
680 match self {
681 Self::Default(route) => Fallback::Default(f(route)),
682 Self::Service(route) => Fallback::Service(f(route)),
683 Self::BoxedHandler(handler) => Fallback::BoxedHandler(handler.map(f)),
684 }
685 }
686
687 fn with_state<S2>(self, state: S) -> Fallback<S2, E> {
688 match self {
689 Fallback::Default(route) => Fallback::Default(route),
690 Fallback::Service(route) => Fallback::Service(route),
691 Fallback::BoxedHandler(handler) => Fallback::Service(handler.into_route(state)),
692 }
693 }
694
695 fn call_with_state(self, req: Request, state: S) -> RouteFuture<E> {
696 match self {
697 Fallback::Default(route) | Fallback::Service(route) => route.oneshot_inner_owned(req),
698 Fallback::BoxedHandler(handler) => {
699 let route = handler.clone().into_route(state);
700 route.oneshot_inner_owned(req)
701 }
702 }
703 }
704}
705
706impl<S, E> Clone for Fallback<S, E> {
707 fn clone(&self) -> Self {
708 match self {
709 Self::Default(inner) => Self::Default(inner.clone()),
710 Self::Service(inner) => Self::Service(inner.clone()),
711 Self::BoxedHandler(inner) => Self::BoxedHandler(inner.clone()),
712 }
713 }
714}
715
716impl<S, E> fmt::Debug for Fallback<S, E> {
717 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
718 match self {
719 Self::Default(inner) => f.debug_tuple("Default").field(inner).finish(),
720 Self::Service(inner) => f.debug_tuple("Service").field(inner).finish(),
721 Self::BoxedHandler(_) => f.debug_tuple("BoxedHandler").finish(),
722 }
723 }
724}
725
726#[allow(clippy::large_enum_variant)]
727enum Endpoint<S> {
728 MethodRouter(MethodRouter<S>),
729 Route(Route),
730}
731
732impl<S> Endpoint<S>
733where
734 S: Clone + Send + Sync + 'static,
735{
736 fn layer<L>(self, layer: L) -> Endpoint<S>
737 where
738 L: Layer<Route> + Clone + Send + Sync + 'static,
739 L::Service: Service<Request> + Clone + Send + Sync + 'static,
740 <L::Service as Service<Request>>::Response: IntoResponse + 'static,
741 <L::Service as Service<Request>>::Error: Into<Infallible> + 'static,
742 <L::Service as Service<Request>>::Future: Send + 'static,
743 {
744 match self {
745 Endpoint::MethodRouter(method_router) => {
746 Endpoint::MethodRouter(method_router.layer(layer))
747 }
748 Endpoint::Route(route) => Endpoint::Route(route.layer(layer)),
749 }
750 }
751}
752
753impl<S> Clone for Endpoint<S> {
754 fn clone(&self) -> Self {
755 match self {
756 Self::MethodRouter(inner) => Self::MethodRouter(inner.clone()),
757 Self::Route(inner) => Self::Route(inner.clone()),
758 }
759 }
760}
761
762impl<S> fmt::Debug for Endpoint<S> {
763 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
764 match self {
765 Self::MethodRouter(method_router) => {
766 f.debug_tuple("MethodRouter").field(method_router).finish()
767 }
768 Self::Route(route) => f.debug_tuple("Route").field(route).finish(),
769 }
770 }
771}
772
773#[test]
774fn traits() {
775 use crate::test_helpers::*;
776 assert_send::<Router<()>>();
777 assert_sync::<Router<()>>();
778}