Escape exact gRPC method matches

This commit is contained in:
Nick 2026-05-22 05:42:06 -04:00 committed by GitHub
parent 1c9a3d21ed
commit ee07d0f4d2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 47 additions and 11 deletions

View file

@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"net"
"regexp"
"strconv"
"strings"
@ -394,14 +395,24 @@ func buildGRPCMethodRule(method *gatev1.GRPCMethodMatch) string {
return `PathPrefix("/")`
}
isExact := method.Type == nil || *method.Type == gatev1.GRPCMethodMatchExact
sExpr := "[^/]+"
if s := ptr.Deref(method.Service, ""); s != "" {
sExpr = s
if isExact {
sExpr = regexp.QuoteMeta(s)
} else {
sExpr = s
}
}
mExpr := "[^/]+"
if m := ptr.Deref(method.Method, ""); m != "" {
mExpr = m
if isExact {
mExpr = regexp.QuoteMeta(m)
} else {
mExpr = m
}
}
return fmt.Sprintf("PathRegexp(%q)", fmt.Sprintf("/%s/%s", sExpr, mExpr))

View file

@ -118,15 +118,6 @@ func Test_buildGRPCMethodRule(t *testing.T) {
},
expectedRule: `PathRegexp("/[^/]+/bar")`,
},
{
desc: "Exact service and method matching",
method: &gatev1.GRPCMethodMatch{
Type: ptr.To(gatev1.GRPCMethodMatchExact),
Service: ptr.To("foo"),
Method: ptr.To("bar"),
},
expectedRule: `PathRegexp("/foo/bar")`,
},
{
desc: "Regexp service matching",
method: &gatev1.GRPCMethodMatch{
@ -152,6 +143,40 @@ func Test_buildGRPCMethodRule(t *testing.T) {
},
expectedRule: `PathRegexp("/[^1-9/]/[^1-9/]")`,
},
{
desc: "Exact type with dot in service name escapes dot",
method: &gatev1.GRPCMethodMatch{
Type: ptr.To(gatev1.GRPCMethodMatchExact),
Service: ptr.To("foo.bar"),
Method: ptr.To("Method"),
},
expectedRule: `PathRegexp("/foo\\.bar/Method")`,
},
{
desc: "Nil type defaults to exact and escapes dot",
method: &gatev1.GRPCMethodMatch{
Type: nil,
Service: ptr.To("auth.api"),
Method: ptr.To("Login"),
},
expectedRule: `PathRegexp("/auth\\.api/Login")`,
},
{
desc: "RegularExpression type preserves dot as regex wildcard",
method: &gatev1.GRPCMethodMatch{
Type: ptr.To(gatev1.GRPCMethodMatchRegularExpression),
Service: ptr.To("foo.bar"),
Method: ptr.To(".*"),
},
expectedRule: `PathRegexp("/foo.bar/.*")`,
},
{
desc: "Exact type with neither service nor method uses full wildcard",
method: &gatev1.GRPCMethodMatch{
Type: ptr.To(gatev1.GRPCMethodMatchExact),
},
expectedRule: `PathRegexp("/[^/]+/[^/]+")`,
},
}
for _, test := range testCases {