@@ -55,7 +55,7 @@ impl Router {
55
55
} ;
56
56
57
57
if let Some ( match_part) = match_candidate. parts . get ( idx) {
58
- if !match_part. is_dynamic && !match_part. value . eq ( part) {
58
+ if !match_part. is_dynamic && !match_part. name . eq ( part) {
59
59
trace ! (
60
60
"excluding server route from search because part differ and not dynamic: {:?}" ,
61
61
match_candidate
@@ -251,7 +251,10 @@ impl StoredRoute {
251
251
bail ! ( "nested `:` is not allowed in dynamic route part" ) ;
252
252
}
253
253
254
- parts. push ( RoutePart { is_dynamic, value } ) ;
254
+ parts. push ( RoutePart {
255
+ is_dynamic,
256
+ name : value,
257
+ } ) ;
255
258
}
256
259
257
260
Ok ( Self {
@@ -264,17 +267,18 @@ impl StoredRoute {
264
267
pub fn extract_routing_data ( & self , request_url : & str ) -> Result < RoutingData > {
265
268
let request_parts: Vec < _ > = request_url. split ( '/' ) . filter ( |p| !p. is_empty ( ) ) . collect ( ) ;
266
269
267
- let mut params: HashMap < String , String > = HashMap :: new ( ) ;
270
+ let mut params: HashMap < String , Option < String > > = HashMap :: new ( ) ;
268
271
for ( idx, part) in self . parts . iter ( ) . enumerate ( ) {
269
272
if !part. is_dynamic {
270
273
continue ;
271
274
}
272
275
273
- let part_value = * request_parts
274
- . get ( idx)
275
- . context ( "part `{part_idx}` should exist" ) ?;
276
+ let value: Option < String > = match request_parts. get ( idx) {
277
+ Some ( & value) => Some ( value. to_owned ( ) ) ,
278
+ None => None ,
279
+ } ;
276
280
277
- params. insert ( part. value . to_owned ( ) , part_value . to_owned ( ) ) ;
281
+ params. insert ( part. name . to_owned ( ) , value ) ;
278
282
}
279
283
280
284
Ok ( RoutingData { params } )
@@ -284,7 +288,7 @@ impl StoredRoute {
284
288
#[ derive( Debug , Hash , Eq , PartialEq , Clone ) ]
285
289
pub struct RoutePart {
286
290
pub is_dynamic : bool ,
287
- pub value : String ,
291
+ pub name : String ,
288
292
}
289
293
290
294
#[ derive( Debug , Hash , Eq , PartialEq , Clone ) ]
@@ -317,7 +321,17 @@ type RoutingCallback = fn(&HttpRequest, &RoutingData) -> Result<HttpResponse>;
317
321
318
322
#[ derive( Debug , Default ) ]
319
323
pub struct RoutingData {
320
- pub params : HashMap < String , String > ,
324
+ params : HashMap < String , Option < String > > ,
325
+ }
326
+
327
+ impl RoutingData {
328
+ pub fn get_value ( & self , param_name : & str ) -> Result < Option < String > > {
329
+ if let Some ( param_value) = self . params . get ( param_name) {
330
+ Ok ( param_value. to_owned ( ) )
331
+ } else {
332
+ bail ! ( "no such route parameter: {param_name}" )
333
+ }
334
+ }
321
335
}
322
336
323
337
#[ cfg( test) ]
@@ -356,16 +370,26 @@ mod tests {
356
370
}
357
371
358
372
fn get_user_by_id ( _request : & HttpRequest , routing_data : & RoutingData ) -> Result < HttpResponse > {
359
- let id = routing_data. params . get ( "id" ) . unwrap ( ) ;
373
+ let id = routing_data
374
+ . get_value ( "id" )
375
+ . unwrap ( )
376
+ . unwrap_or ( String :: new ( ) ) ;
360
377
let username = format ! ( "user_{id}" ) ;
361
378
let json = json ! ( { "username" : username } ) ;
362
379
363
380
HttpResponseBuilder :: new ( ) . set_json_body ( & json) ?. build ( )
364
381
}
365
382
366
383
fn get_user_info ( _request : & HttpRequest , routing_data : & RoutingData ) -> Result < HttpResponse > {
367
- let id = routing_data. params . get ( "id" ) . unwrap ( ) ;
368
- let info_field = routing_data. params . get ( "field" ) . unwrap ( ) ;
384
+ let id = routing_data
385
+ . get_value ( "id" )
386
+ . unwrap ( )
387
+ . unwrap_or ( String :: new ( ) ) ;
388
+
389
+ let info_field = routing_data
390
+ . get_value ( "field" )
391
+ . unwrap ( )
392
+ . unwrap_or ( String :: new ( ) ) ;
369
393
370
394
let username = format ! ( "user_{id}" ) ;
371
395
let json = json ! ( { "username" : username, "field" : info_field } ) ;
0 commit comments