Skip to content

Commit cb399bb

Browse files
committed
fix: change RouteData param values to Option<String> + fix bug when no value for param + add method
1 parent e242053 commit cb399bb

File tree

1 file changed

+36
-12
lines changed

1 file changed

+36
-12
lines changed

src/router.rs

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ impl Router {
5555
};
5656

5757
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) {
5959
trace!(
6060
"excluding server route from search because part differ and not dynamic: {:?}",
6161
match_candidate
@@ -251,7 +251,10 @@ impl StoredRoute {
251251
bail!("nested `:` is not allowed in dynamic route part");
252252
}
253253

254-
parts.push(RoutePart { is_dynamic, value });
254+
parts.push(RoutePart {
255+
is_dynamic,
256+
name: value,
257+
});
255258
}
256259

257260
Ok(Self {
@@ -264,17 +267,18 @@ impl StoredRoute {
264267
pub fn extract_routing_data(&self, request_url: &str) -> Result<RoutingData> {
265268
let request_parts: Vec<_> = request_url.split('/').filter(|p| !p.is_empty()).collect();
266269

267-
let mut params: HashMap<String, String> = HashMap::new();
270+
let mut params: HashMap<String, Option<String>> = HashMap::new();
268271
for (idx, part) in self.parts.iter().enumerate() {
269272
if !part.is_dynamic {
270273
continue;
271274
}
272275

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+
};
276280

277-
params.insert(part.value.to_owned(), part_value.to_owned());
281+
params.insert(part.name.to_owned(), value);
278282
}
279283

280284
Ok(RoutingData { params })
@@ -284,7 +288,7 @@ impl StoredRoute {
284288
#[derive(Debug, Hash, Eq, PartialEq, Clone)]
285289
pub struct RoutePart {
286290
pub is_dynamic: bool,
287-
pub value: String,
291+
pub name: String,
288292
}
289293

290294
#[derive(Debug, Hash, Eq, PartialEq, Clone)]
@@ -317,7 +321,17 @@ type RoutingCallback = fn(&HttpRequest, &RoutingData) -> Result<HttpResponse>;
317321

318322
#[derive(Debug, Default)]
319323
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+
}
321335
}
322336

323337
#[cfg(test)]
@@ -356,16 +370,26 @@ mod tests {
356370
}
357371

358372
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());
360377
let username = format!("user_{id}");
361378
let json = json!({ "username": username });
362379

363380
HttpResponseBuilder::new().set_json_body(&json)?.build()
364381
}
365382

366383
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());
369393

370394
let username = format!("user_{id}");
371395
let json = json!({ "username": username, "field": info_field });

0 commit comments

Comments
 (0)