3
3
use self :: { future:: RouteFuture , not_found:: NotFound , path_router:: PathRouter } ;
4
4
#[ cfg( feature = "tokio" ) ]
5
5
use crate :: extract:: connect_info:: IntoMakeServiceWithConnectInfo ;
6
+ #[ cfg( feature = "matched-path" ) ]
7
+ use crate :: extract:: MatchedPath ;
6
8
use crate :: {
7
9
body:: { Body , HttpBody } ,
8
10
boxed:: BoxedIntoRoute ,
@@ -20,7 +22,8 @@ use std::{
20
22
sync:: Arc ,
21
23
task:: { Context , Poll } ,
22
24
} ;
23
- use tower_layer:: Layer ;
25
+ use tower:: service_fn;
26
+ use tower_layer:: { layer_fn, Layer } ;
24
27
use tower_service:: Service ;
25
28
26
29
pub mod future;
@@ -78,8 +81,7 @@ impl<S> Clone for Router<S> {
78
81
}
79
82
80
83
struct RouterInner < S > {
81
- path_router : PathRouter < S , false > ,
82
- fallback_router : PathRouter < S , true > ,
84
+ path_router : PathRouter < S > ,
83
85
default_fallback : bool ,
84
86
catch_all_fallback : Fallback < S > ,
85
87
}
@@ -97,7 +99,6 @@ impl<S> fmt::Debug for Router<S> {
97
99
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
98
100
f. debug_struct ( "Router" )
99
101
. field ( "path_router" , & self . inner . path_router )
100
- . field ( "fallback_router" , & self . inner . fallback_router )
101
102
. field ( "default_fallback" , & self . inner . default_fallback )
102
103
. field ( "catch_all_fallback" , & self . inner . catch_all_fallback )
103
104
. finish ( )
@@ -147,7 +148,6 @@ where
147
148
Self {
148
149
inner : Arc :: new ( RouterInner {
149
150
path_router : Default :: default ( ) ,
150
- fallback_router : PathRouter :: new_fallback ( ) ,
151
151
default_fallback : true ,
152
152
catch_all_fallback : Fallback :: Default ( Route :: new ( NotFound ) ) ,
153
153
} ) ,
@@ -159,7 +159,6 @@ where
159
159
Ok ( inner) => inner,
160
160
Err ( arc) => RouterInner {
161
161
path_router : arc. path_router . clone ( ) ,
162
- fallback_router : arc. fallback_router . clone ( ) ,
163
162
default_fallback : arc. default_fallback ,
164
163
catch_all_fallback : arc. catch_all_fallback . clone ( ) ,
165
164
} ,
@@ -213,8 +212,7 @@ where
213
212
214
213
let RouterInner {
215
214
path_router,
216
- fallback_router,
217
- default_fallback,
215
+ default_fallback : _,
218
216
// we don't need to inherit the catch-all fallback. It is only used for CONNECT
219
217
// requests with an empty path. If we were to inherit the catch-all fallback
220
218
// it would end up matching `/{path}/*` which doesn't match empty paths.
@@ -223,10 +221,6 @@ where
223
221
224
222
tap_inner ! ( self , mut this => {
225
223
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
224
} )
231
225
}
232
226
@@ -253,43 +247,33 @@ where
253
247
where
254
248
R : Into < Router < S > > ,
255
249
{
256
- const PANIC_MSG : & str =
257
- "Failed to merge fallbacks. This is a bug in axum. Please file an issue" ;
258
-
259
250
let other: Router < S > = other. into ( ) ;
260
251
let RouterInner {
261
252
path_router,
262
- fallback_router : mut other_fallback,
263
253
default_fallback,
264
254
catch_all_fallback,
265
255
} = other. into_inner ( ) ;
266
256
267
257
map_inner ! ( self , mut this => {
268
- panic_on_err!( this. path_router. merge( path_router) ) ;
269
-
270
258
match ( this. default_fallback, default_fallback) {
271
259
// both have the default fallback
272
260
// use the one from other
273
- ( true , true ) => {
274
- this. fallback_router. merge( other_fallback) . expect( PANIC_MSG ) ;
275
- }
261
+ ( true , true ) => { }
276
262
// this has default fallback, other has a custom fallback
277
263
( true , false ) => {
278
- this. fallback_router. merge( other_fallback) . expect( PANIC_MSG ) ;
279
264
this. default_fallback = false ;
280
265
}
281
266
// this has a custom fallback, other has a default
282
267
( 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
268
}
287
269
// both have a custom fallback, not allowed
288
270
( false , false ) => {
289
271
panic!( "Cannot merge two `Router`s that both have a fallback" )
290
272
}
291
273
} ;
292
274
275
+ panic_on_err!( this. path_router. merge( path_router) ) ;
276
+
293
277
this. catch_all_fallback = this
294
278
. catch_all_fallback
295
279
. merge( catch_all_fallback)
@@ -310,7 +294,6 @@ where
310
294
{
311
295
map_inner ! ( self , this => RouterInner {
312
296
path_router: this. path_router. layer( layer. clone( ) ) ,
313
- fallback_router: this. fallback_router. layer( layer. clone( ) ) ,
314
297
default_fallback: this. default_fallback,
315
298
catch_all_fallback: this. catch_all_fallback. map( |route| route. layer( layer) ) ,
316
299
} )
@@ -328,7 +311,6 @@ where
328
311
{
329
312
map_inner ! ( self , this => RouterInner {
330
313
path_router: this. path_router. route_layer( layer) ,
331
- fallback_router: this. fallback_router,
332
314
default_fallback: this. default_fallback,
333
315
catch_all_fallback: this. catch_all_fallback,
334
316
} )
@@ -397,8 +379,51 @@ where
397
379
}
398
380
399
381
fn fallback_endpoint ( self , endpoint : Endpoint < S > ) -> Self {
382
+ // TODO make this better, get rid of the `unwrap`s.
383
+ // We need the returned `Service` to be `Clone` and the function inside `service_fn` to be
384
+ // `FnMut` so instead of just using the owned service, we do this trick with `Option`. We
385
+ // know this will be called just once so it's fine. We're doing that so that we avoid one
386
+ // clone inside `oneshot_inner` so that the `Router` and subsequently the `State` is not
387
+ // cloned too much.
400
388
tap_inner ! ( self , mut this => {
401
- this. fallback_router. set_fallback( endpoint) ;
389
+ _ = this. path_router. route_endpoint(
390
+ "/" ,
391
+ endpoint. clone( ) . layer(
392
+ layer_fn(
393
+ |service: Route | {
394
+ let mut service = Some ( service) ;
395
+ service_fn(
396
+ #[ cfg_attr( not( feature = "matched-path" ) , allow( unused_mut) ) ]
397
+ move |mut request: Request | {
398
+ #[ cfg( feature = "matched-path" ) ]
399
+ request. extensions_mut( ) . remove:: <MatchedPath >( ) ;
400
+ service. take( ) . unwrap( ) . oneshot_inner_owned( request)
401
+ }
402
+ )
403
+ }
404
+ )
405
+ )
406
+ ) ;
407
+
408
+ _ = this. path_router. route_endpoint(
409
+ FALLBACK_PARAM_PATH ,
410
+ endpoint. layer(
411
+ layer_fn(
412
+ |service: Route | {
413
+ let mut service = Some ( service) ;
414
+ service_fn(
415
+ #[ cfg_attr( not( feature = "matched-path" ) , allow( unused_mut) ) ]
416
+ move |mut request: Request | {
417
+ #[ cfg( feature = "matched-path" ) ]
418
+ request. extensions_mut( ) . remove:: <MatchedPath >( ) ;
419
+ service. take( ) . unwrap( ) . oneshot_inner_owned( request)
420
+ }
421
+ )
422
+ }
423
+ )
424
+ )
425
+ ) ;
426
+
402
427
this. default_fallback = false ;
403
428
} )
404
429
}
@@ -407,7 +432,6 @@ where
407
432
pub fn with_state < S2 > ( self , state : S ) -> Router < S2 > {
408
433
map_inner ! ( self , this => RouterInner {
409
434
path_router: this. path_router. with_state( state. clone( ) ) ,
410
- fallback_router: this. fallback_router. with_state( state. clone( ) ) ,
411
435
default_fallback: this. default_fallback,
412
436
catch_all_fallback: this. catch_all_fallback. with_state( state) ,
413
437
} )
@@ -419,11 +443,6 @@ where
419
443
Err ( ( req, state) ) => ( req, state) ,
420
444
} ;
421
445
422
- let ( req, state) = match self . inner . fallback_router . call_with_state ( req, state) {
423
- Ok ( future) => return future,
424
- Err ( ( req, state) ) => ( req, state) ,
425
- } ;
426
-
427
446
self . inner
428
447
. catch_all_fallback
429
448
. clone ( )
0 commit comments