@@ -6,6 +6,8 @@ use crate::http::{Method, Status};
6
6
use crate :: { Route , Catcher } ;
7
7
use crate :: router:: Collide ;
8
8
9
+ use super :: matcher:: { paths_match, queries_match, formats_match} ;
10
+
9
11
#[ derive( Debug ) ]
10
12
pub ( crate ) struct Router < T > ( T ) ;
11
13
@@ -104,6 +106,38 @@ impl Router<Finalized> {
104
106
. filter ( move |r| r. matches ( req) )
105
107
}
106
108
109
+ pub ( crate ) fn matches_except_formats < ' r , ' a : ' r > (
110
+ & ' a self ,
111
+ req : & ' r Request < ' r >
112
+ ) -> bool {
113
+ self . route_map . get ( & req. method ( ) )
114
+ . into_iter ( )
115
+ . flatten ( )
116
+ . any ( |& route|
117
+ paths_match ( & self . routes [ route] , req)
118
+ &&
119
+ queries_match ( & self . routes [ route] , req)
120
+ &&
121
+ !formats_match ( & self . routes [ route] , req) )
122
+ }
123
+
124
+ const ALL_METHODS : & ' static [ Method ] = & [
125
+ Method :: Get , Method :: Put , Method :: Post , Method :: Delete , Method :: Options ,
126
+ Method :: Head , Method :: Trace , Method :: Connect , Method :: Patch ,
127
+ ] ;
128
+
129
+ pub ( crate ) fn matches_except_method < ' r , ' a : ' r > (
130
+ & ' a self ,
131
+ req : & ' r Request < ' r >
132
+ ) -> bool {
133
+ Self :: ALL_METHODS
134
+ . iter ( )
135
+ . filter ( |method| * method != & req. method ( ) )
136
+ . filter_map ( |method| self . route_map . get ( method) )
137
+ . flatten ( )
138
+ . any ( |route| paths_match ( & self . routes [ * route] , req) )
139
+ }
140
+
107
141
// For many catchers, using aho-corasick or similar should be much faster.
108
142
#[ track_caller]
109
143
pub fn catch < ' r > ( & self , status : Status , req : & ' r Request < ' r > ) -> Option < & Catcher > {
@@ -396,6 +430,25 @@ mod test {
396
430
assert ! ( route( & router, Get , "/prefi/" ) . is_none( ) ) ;
397
431
}
398
432
433
+ fn has_mismatched_method < ' a > (
434
+ router : & ' a Router < Finalized > ,
435
+ method : Method , uri : & ' a str
436
+ ) -> bool {
437
+ let client = Client :: debug_with ( vec ! [ ] ) . expect ( "client" ) ;
438
+ let request = client. req ( method, Origin :: parse ( uri) . unwrap ( ) ) ;
439
+ router. matches_except_method ( & request)
440
+ }
441
+
442
+ #[ test]
443
+ fn test_bad_method_routing ( ) {
444
+ let router = router_with_routes ( & [ "/hello" ] ) ;
445
+ assert ! ( route( & router, Put , "/hello" ) . is_none( ) ) ;
446
+ assert ! ( has_mismatched_method( & router, Put , "/hello" ) ) ;
447
+ assert ! ( has_mismatched_method( & router, Post , "/hello" ) ) ;
448
+
449
+ assert ! ( ! has_mismatched_method( & router, Get , "/hello" ) ) ;
450
+ }
451
+
399
452
/// Asserts that `$to` routes to `$want` given `$routes` are present.
400
453
macro_rules! assert_ranked_match {
401
454
( $routes: expr, $to: expr => $want: expr) => ( {
0 commit comments