Fix server routing matching URIs with prefixes (#1484)

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.
This commit is contained in:
david-perez 2022-06-22 14:06:19 +02:00 committed by GitHub
parent 5d6d8843cd
commit 9f470718f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 35 additions and 7 deletions

View File

@ -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
@ -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")
}
}
@ -250,15 +250,15 @@ 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![
@ -266,7 +266,7 @@ mod tests {
PathSegment::Greedy,
PathSegment::Literal(String::from("suffix")),
]),
"/a/.*/suffix$",
"^/a/.*/suffix$",
),
];
@ -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(