Skip to content

Commit

Permalink
Fix server routing matching URIs with prefixes (#1484)
Browse files Browse the repository at this point in the history
We are incorrectly matching URIs to the spec when the URI has a prefix
that is not in the spec.

This is because when generating the regex describing the spec, we're not
using the `^` anchor to match from the beginning of the text.

Fixes #1483.
  • Loading branch information
david-perez authored Jun 22, 2022
1 parent 5d6d884 commit 9f47071
Showing 1 changed file with 35 additions and 7 deletions.
42 changes: 35 additions & 7 deletions rust-runtime/aws-smithy-http-server/src/routing/request_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ impl From<&PathSpec> for Regex {
fn from(uri_path_spec: &PathSpec) -> Self {
let sep = "/";
let re = if uri_path_spec.0.is_empty() {
String::from("/")
String::from(sep)
} else {
uri_path_spec
.0
Expand All @@ -113,7 +113,7 @@ impl From<&PathSpec> for Regex {
.fold(String::new(), |a, b| a + sep + b)
};

Regex::new(&format!("{}$", re)).unwrap()
Regex::new(&format!("^{}$", re)).expect("invalid `Regex` from `PathSpec`; please file a bug report under https://github.com/awslabs/smithy-rs/issues")
}
}

Expand Down Expand Up @@ -250,23 +250,23 @@ mod tests {
#[test]
fn path_spec_into_regex() {
let cases = vec![
(PathSpec(vec![]), "/$"),
(PathSpec(vec![PathSegment::Literal(String::from("a"))]), "/a$"),
(PathSpec(vec![]), "^/$"),
(PathSpec(vec![PathSegment::Literal(String::from("a"))]), "^/a$"),
(
PathSpec(vec![PathSegment::Literal(String::from("a")), PathSegment::Label]),
"/a/[^/]*$",
"^/a/[^/]*$",
),
(
PathSpec(vec![PathSegment::Literal(String::from("a")), PathSegment::Greedy]),
"/a/.*$",
"^/a/.*$",
),
(
PathSpec(vec![
PathSegment::Literal(String::from("a")),
PathSegment::Greedy,
PathSegment::Literal(String::from("suffix")),
]),
"/a/.*/suffix$",
"^/a/.*/suffix$",
),
];

Expand All @@ -276,6 +276,34 @@ mod tests {
}
}

#[test]
fn paths_must_match_spec_from_the_beginning_literal() {
let spec = RequestSpec::from_parts(
Method::GET,
vec![PathSegment::Literal(String::from("path"))],
Vec::new(),
);

let misses = vec![(Method::GET, "/beta/path"), (Method::GET, "/multiple/stages/in/path")];
for (method, uri) in &misses {
assert_eq!(Match::No, spec.matches(&req(method, uri, None)));
}
}

#[test]
fn paths_must_match_spec_from_the_beginning_label() {
let spec = RequestSpec::from_parts(Method::GET, vec![PathSegment::Label], Vec::new());

let misses = vec![
(Method::GET, "/prefix/label"),
(Method::GET, "/label/suffix"),
(Method::GET, "/prefix/label/suffix"),
];
for (method, uri) in &misses {
assert_eq!(Match::No, spec.matches(&req(method, uri, None)));
}
}

#[test]
fn greedy_labels_match_greedily() {
let spec = RequestSpec::from_parts(
Expand Down

0 comments on commit 9f47071

Please sign in to comment.