parent
67f3da61af
commit
bd4a2d7be2
|
@ -3119,6 +3119,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
|
|||
"match": {
|
||||
"http": {
|
||||
"path_prefix": "/foo",
|
||||
"methods": [ "GET", "DELETE" ],
|
||||
"query_param": [
|
||||
{
|
||||
"name": "hack1",
|
||||
|
@ -3202,6 +3203,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
|
|||
match {
|
||||
http {
|
||||
path_prefix = "/foo"
|
||||
methods = [ "GET", "DELETE" ]
|
||||
query_param = [
|
||||
{
|
||||
name = "hack1"
|
||||
|
@ -3284,6 +3286,7 @@ func TestConfigFlagsAndEdgecases(t *testing.T) {
|
|||
Match: &structs.ServiceRouteMatch{
|
||||
HTTP: &structs.ServiceRouteHTTPMatch{
|
||||
PathPrefix: "/foo",
|
||||
Methods: []string{"GET", "DELETE"},
|
||||
QueryParam: []structs.ServiceRouteHTTPMatchQueryParam{
|
||||
{
|
||||
Name: "hack1",
|
||||
|
|
|
@ -58,6 +58,21 @@ func (e *ServiceRouterConfigEntry) Normalize() error {
|
|||
|
||||
e.Kind = ServiceRouter
|
||||
|
||||
for _, route := range e.Routes {
|
||||
if route.Match == nil || route.Match.HTTP == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
httpMatch := route.Match.HTTP
|
||||
if len(httpMatch.Methods) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
for j := 0; j < len(httpMatch.Methods); j++ {
|
||||
httpMatch.Methods[j] = strings.ToUpper(httpMatch.Methods[j])
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -139,6 +154,16 @@ func (e *ServiceRouterConfigEntry) Validate() error {
|
|||
return fmt.Errorf("Route[%d] QueryParam[%d] should only contain one of Present, Exact, or Regex", i, j)
|
||||
}
|
||||
}
|
||||
|
||||
if len(route.Match.HTTP.Methods) > 0 {
|
||||
found := make(map[string]struct{})
|
||||
for _, m := range route.Match.HTTP.Methods {
|
||||
if _, ok := found[m]; ok {
|
||||
return fmt.Errorf("Route[%d] Methods contains %q more than once", i, m)
|
||||
}
|
||||
found[m] = struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if route.Destination != nil {
|
||||
|
@ -218,9 +243,7 @@ type ServiceRouteHTTPMatch struct {
|
|||
|
||||
Header []ServiceRouteHTTPMatchHeader `json:",omitempty"`
|
||||
QueryParam []ServiceRouteHTTPMatchQueryParam `json:",omitempty"`
|
||||
|
||||
// TODO(rb): reenable Methods
|
||||
// Methods []string `json:",omitempty"`
|
||||
Methods []string `json:",omitempty"`
|
||||
}
|
||||
|
||||
func (m *ServiceRouteHTTPMatch) IsEmpty() bool {
|
||||
|
@ -228,8 +251,8 @@ func (m *ServiceRouteHTTPMatch) IsEmpty() bool {
|
|||
m.PathPrefix == "" &&
|
||||
m.PathRegex == "" &&
|
||||
len(m.Header) == 0 &&
|
||||
len(m.QueryParam) == 0
|
||||
// && len(m.Methods) == 0
|
||||
len(m.QueryParam) == 0 &&
|
||||
len(m.Methods) == 0
|
||||
}
|
||||
|
||||
type ServiceRouteHTTPMatchHeader struct {
|
||||
|
|
|
@ -1099,6 +1099,28 @@ func TestServiceRouterConfigEntry(t *testing.T) {
|
|||
}),
|
||||
validateErr: "cannot make use of PrefixRewrite without configuring either PathExact or PathPrefix",
|
||||
},
|
||||
////////////////
|
||||
{
|
||||
name: "route with method matches",
|
||||
entry: makerouter(routeMatch(httpMatch(&ServiceRouteHTTPMatch{
|
||||
Methods: []string{
|
||||
"get", "POST", "dElEtE",
|
||||
},
|
||||
}))),
|
||||
check: func(t *testing.T, entry *ServiceRouterConfigEntry) {
|
||||
m := entry.Routes[0].Match.HTTP.Methods
|
||||
require.Equal(t, []string{"GET", "POST", "DELETE"}, m)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "route with method matches repeated",
|
||||
entry: makerouter(routeMatch(httpMatch(&ServiceRouteHTTPMatch{
|
||||
Methods: []string{
|
||||
"GET", "DELETE", "get",
|
||||
},
|
||||
}))),
|
||||
validateErr: "Methods contains \"GET\" more than once",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
|
|
|
@ -168,6 +168,7 @@ func TestDecodeConfigEntry(t *testing.T) {
|
|||
match {
|
||||
http {
|
||||
path_prefix = "/foo"
|
||||
methods = [ "GET", "DELETE" ]
|
||||
query_param = [
|
||||
{
|
||||
name = "hack1"
|
||||
|
@ -246,6 +247,7 @@ func TestDecodeConfigEntry(t *testing.T) {
|
|||
Match {
|
||||
HTTP {
|
||||
PathPrefix = "/foo"
|
||||
Methods = [ "GET", "DELETE" ]
|
||||
QueryParam = [
|
||||
{
|
||||
Name = "hack1"
|
||||
|
@ -324,6 +326,7 @@ func TestDecodeConfigEntry(t *testing.T) {
|
|||
Match: &ServiceRouteMatch{
|
||||
HTTP: &ServiceRouteHTTPMatch{
|
||||
PathPrefix: "/foo",
|
||||
Methods: []string{"GET", "DELETE"},
|
||||
QueryParam: []ServiceRouteHTTPMatchQueryParam{
|
||||
{
|
||||
Name: "hack1",
|
||||
|
|
|
@ -3,6 +3,7 @@ package xds
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
|
||||
|
@ -252,6 +253,18 @@ func makeRouteMatchForDiscoveryRoute(discoveryRoute *structs.DiscoveryRoute, pro
|
|||
}
|
||||
}
|
||||
|
||||
if len(match.HTTP.Methods) > 0 {
|
||||
methodHeaderRegex := strings.Join(match.HTTP.Methods, "|")
|
||||
|
||||
eh := &envoyroute.HeaderMatcher{
|
||||
Name: ":method",
|
||||
HeaderMatchSpecifier: &envoyroute.HeaderMatcher_RegexMatch{
|
||||
RegexMatch: methodHeaderRegex,
|
||||
},
|
||||
}
|
||||
em.Headers = append(em.Headers, eh)
|
||||
}
|
||||
|
||||
if len(match.HTTP.QueryParam) > 0 {
|
||||
em.QueryParameters = make([]*envoyroute.QueryParameterMatcher, 0, len(match.HTTP.QueryParam))
|
||||
for _, qm := range match.HTTP.QueryParam {
|
||||
|
|
|
@ -190,6 +190,24 @@ func TestRoutesFromSnapshot(t *testing.T) {
|
|||
}),
|
||||
Destination: toService("hdr-regex"),
|
||||
},
|
||||
{
|
||||
Match: httpMatch(&structs.ServiceRouteHTTPMatch{
|
||||
Methods: []string{"GET", "PUT"},
|
||||
}),
|
||||
Destination: toService("just-methods"),
|
||||
},
|
||||
{
|
||||
Match: httpMatch(&structs.ServiceRouteHTTPMatch{
|
||||
Header: []structs.ServiceRouteHTTPMatchHeader{
|
||||
{
|
||||
Name: "x-debug",
|
||||
Exact: "exact",
|
||||
},
|
||||
},
|
||||
Methods: []string{"GET", "PUT"},
|
||||
}),
|
||||
Destination: toService("hdr-exact-with-method"),
|
||||
},
|
||||
{
|
||||
Match: httpMatchParam(structs.ServiceRouteHTTPMatchQueryParam{
|
||||
Name: "secretparam1",
|
||||
|
|
|
@ -120,6 +120,38 @@
|
|||
"cluster": "hdr-regex.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": {
|
||||
"prefix": "/",
|
||||
"headers": [
|
||||
{
|
||||
"name": ":method",
|
||||
"regexMatch": "GET|PUT"
|
||||
}
|
||||
]
|
||||
},
|
||||
"route": {
|
||||
"cluster": "just-methods.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": {
|
||||
"prefix": "/",
|
||||
"headers": [
|
||||
{
|
||||
"name": "x-debug",
|
||||
"exactMatch": "exact"
|
||||
},
|
||||
{
|
||||
"name": ":method",
|
||||
"regexMatch": "GET|PUT"
|
||||
}
|
||||
]
|
||||
},
|
||||
"route": {
|
||||
"cluster": "hdr-exact-with-method.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": {
|
||||
"prefix": "/",
|
||||
|
|
|
@ -33,9 +33,7 @@ type ServiceRouteHTTPMatch struct {
|
|||
|
||||
Header []ServiceRouteHTTPMatchHeader `json:",omitempty"`
|
||||
QueryParam []ServiceRouteHTTPMatchQueryParam `json:",omitempty"`
|
||||
|
||||
// TODO(rb): reenable Methods
|
||||
// Methods []string `json:",omitempty"`
|
||||
Methods []string `json:",omitempty"`
|
||||
}
|
||||
|
||||
type ServiceRouteHTTPMatchHeader struct {
|
||||
|
|
|
@ -262,6 +262,7 @@ func TestParseConfigEntry(t *testing.T) {
|
|||
match {
|
||||
http {
|
||||
path_prefix = "/foo"
|
||||
methods = [ "GET", "DELETE" ]
|
||||
query_param = [
|
||||
{
|
||||
name = "hack1"
|
||||
|
@ -340,6 +341,7 @@ func TestParseConfigEntry(t *testing.T) {
|
|||
Match {
|
||||
HTTP {
|
||||
PathPrefix = "/foo"
|
||||
Methods = [ "GET", "DELETE" ]
|
||||
QueryParam = [
|
||||
{
|
||||
Name = "hack1"
|
||||
|
@ -418,6 +420,7 @@ func TestParseConfigEntry(t *testing.T) {
|
|||
Match: &api.ServiceRouteMatch{
|
||||
HTTP: &api.ServiceRouteHTTPMatch{
|
||||
PathPrefix: "/foo",
|
||||
Methods: []string{"GET", "DELETE"},
|
||||
QueryParam: []api.ServiceRouteHTTPMatchQueryParam{
|
||||
{
|
||||
Name: "hack1",
|
||||
|
|
|
@ -193,6 +193,9 @@ routes = [
|
|||
|
||||
At most only one of `Exact`, `Regex`, or `Present` may be configured.
|
||||
|
||||
- `Methods` `(array<string>)` - A list of HTTP methods for which this match
|
||||
applies. If unspecified all http methods are matched.
|
||||
|
||||
- `Destination` `(ServiceRouteDestination: <optional>)` - Controls how to
|
||||
proxy the actual matching request to a service.
|
||||
|
||||
|
|
Loading…
Reference in New Issue