From 24150d00c263d6aa99e72db7a9259f4fef91ce86 Mon Sep 17 00:00:00 2001 From: James Hamlin Date: Wed, 1 Aug 2018 16:54:45 -0700 Subject: [PATCH] Add test case and proposed fix for path component with trailing colon (and string) (#708) * If a pattern has no verb, match with a verb arg appended to last component Parsing out a "verb" from the input path is a convenience for parsing. Whether the colon and string are _actually_ a verb depends on the matching HTTP rule. This change gives a verb-less pattern a chance to match a path by assuming the colon+string suffix are a part of the final component. Fixes #224 Signed-off-by: James Hamlin --- runtime/mux.go | 1 + runtime/mux_test.go | 32 ++++++++++++++++++++++++++++++++ runtime/pattern.go | 11 ++++++++++- 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/runtime/mux.go b/runtime/mux.go index 1d4c75760fe..6c06ab8c222 100644 --- a/runtime/mux.go +++ b/runtime/mux.go @@ -7,6 +7,7 @@ import ( "strings" "context" + "github.com/golang/protobuf/proto" "google.golang.org/grpc/codes" "google.golang.org/grpc/metadata" diff --git a/runtime/mux_test.go b/runtime/mux_test.go index bb90a7306a1..a0f15f7ae4e 100644 --- a/runtime/mux_test.go +++ b/runtime/mux_test.go @@ -176,6 +176,38 @@ func TestMuxServeHTTP(t *testing.T) { respStatus: http.StatusOK, respContent: "POST /foo:bar", }, + { + patterns: []stubPattern{ + { + method: "GET", + ops: []int{int(utilities.OpLitPush), 0, int(utilities.OpPush), 0, int(utilities.OpConcatN), 1, int(utilities.OpCapture), 1}, + pool: []string{"foo", "id"}, + }, + }, + reqMethod: "GET", + reqPath: "/foo/bar", + headers: map[string]string{ + "Content-Type": "application/json", + }, + respStatus: http.StatusOK, + respContent: "GET /foo/{id=*}", + }, + { + patterns: []stubPattern{ + { + method: "GET", + ops: []int{int(utilities.OpLitPush), 0, int(utilities.OpPush), 0, int(utilities.OpConcatN), 1, int(utilities.OpCapture), 1}, + pool: []string{"foo", "id"}, + }, + }, + reqMethod: "GET", + reqPath: "/foo/bar:123", + headers: map[string]string{ + "Content-Type": "application/json", + }, + respStatus: http.StatusOK, + respContent: "GET /foo/{id=*}", + }, } { mux := runtime.NewServeMux() for _, p := range spec.patterns { diff --git a/runtime/pattern.go b/runtime/pattern.go index f16a84ad389..223a12ecc43 100644 --- a/runtime/pattern.go +++ b/runtime/pattern.go @@ -144,7 +144,16 @@ func MustPattern(p Pattern, err error) Pattern { // If otherwise, the function returns an error. func (p Pattern) Match(components []string, verb string) (map[string]string, error) { if p.verb != verb { - return nil, ErrNotMatch + if p.verb != "" { + return nil, ErrNotMatch + } + if len(components) == 0 { + components = []string{":" + verb} + } else { + components = append([]string{}, components...) + components[len(components)-1] += ":" + verb + } + verb = "" } var pos int