Unverified Commit 9f470718 authored by david-perez's avatar david-perez Committed by GitHub
Browse files

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.
parent 5d6d8843
Loading
Loading
Loading
Loading
+35 −7
Original line number Diff line number Diff line
@@ -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(