From 72332c6c0ed228e3154b703f64f6f550dac1eee2 Mon Sep 17 00:00:00 2001 From: Yun Long Date: Wed, 1 Nov 2023 19:17:15 +0800 Subject: [PATCH] Expose route for context --- pkg/context/context.go | 12 ++++++++++++ pkg/filters/redirectorv2/redirectorv2.go | 13 +++++++------ pkg/filters/redirectorv2/redirectorv2_test.go | 14 +++++++++++--- pkg/object/httpserver/mux.go | 5 ++++- pkg/object/httpserver/routers/routers.go | 10 ++++++++++ pkg/object/httpserver/routers/spec.go | 15 +++++++++++++++ 6 files changed, 59 insertions(+), 10 deletions(-) diff --git a/pkg/context/context.go b/pkg/context/context.go index 8c59176cf1..e69f1b2ba0 100644 --- a/pkg/context/context.go +++ b/pkg/context/context.go @@ -23,6 +23,7 @@ import ( "runtime/debug" "github.com/megaease/easegress/v2/pkg/logger" + "github.com/megaease/easegress/v2/pkg/object/httpserver/routers" "github.com/megaease/easegress/v2/pkg/protocols" "github.com/megaease/easegress/v2/pkg/tracing" ) @@ -73,6 +74,7 @@ type Context struct { activeNs string + route routers.Route requests map[string]*requestRef responses map[string]*responseRef @@ -92,6 +94,16 @@ func New(span *tracing.Span) *Context { return ctx } +// SetRoute sets the route. +func (ctx *Context) SetRoute(route routers.Route) { + ctx.route = route +} + +// GetRoute returns the route. +func (ctx *Context) GetRoute() routers.Route { + return ctx.route +} + // Span returns the span of this Context. func (ctx *Context) Span() *tracing.Span { return ctx.span diff --git a/pkg/filters/redirectorv2/redirectorv2.go b/pkg/filters/redirectorv2/redirectorv2.go index 9f4ccad89e..1a556c0ee9 100644 --- a/pkg/filters/redirectorv2/redirectorv2.go +++ b/pkg/filters/redirectorv2/redirectorv2.go @@ -25,6 +25,7 @@ import ( "github.com/megaease/easegress/v2/pkg/context" "github.com/megaease/easegress/v2/pkg/filters" + "github.com/megaease/easegress/v2/pkg/logger" "github.com/megaease/easegress/v2/pkg/protocols/httpprot" gwapis "sigs.k8s.io/gateway-api/apis/v1beta1" @@ -76,7 +77,6 @@ type ( Spec struct { filters.BaseSpec `json:",inline"` - PathPrefix *string `json:"pathPrefix,omitempty"` gwapis.HTTPRequestRedirectFilter `json:",inline"` } ) @@ -108,10 +108,6 @@ func (s *Spec) Validate() error { return errors.New("invalid path of Redirector, replaceFullPath can't be empty") } case gwapis.PrefixMatchHTTPPathModifier: - if s.PathPrefix == nil || *s.PathPrefix == "" { - return errors.New("invalid path of Redirector, pathPrefix can't be empty") - } - if s.Path.ReplacePrefixMatch == nil { return errors.New("invalid path of Redirector, replacePrefixMatch can't be empty") } @@ -178,8 +174,13 @@ func (r *Redirector) Handle(ctx *context.Context) string { case gwapis.FullPathHTTPPathModifier: redirectURL.Path = string(*r.spec.Path.ReplaceFullPath) case gwapis.PrefixMatchHTTPPathModifier: + prefix := ctx.GetRoute().GetPathPrefix() + if prefix == "" { + logger.Warnf("route %+v has no path prefix", ctx.GetRoute()) + } + redirectURL.Path = r.subPrefix(redirectURL.Path, - *r.spec.PathPrefix, string(*r.spec.Path.ReplacePrefixMatch)) + prefix, string(*r.spec.Path.ReplacePrefixMatch)) } } diff --git a/pkg/filters/redirectorv2/redirectorv2_test.go b/pkg/filters/redirectorv2/redirectorv2_test.go index 4e455c9af8..2b3ade87fa 100644 --- a/pkg/filters/redirectorv2/redirectorv2_test.go +++ b/pkg/filters/redirectorv2/redirectorv2_test.go @@ -22,12 +22,19 @@ import ( "testing" "github.com/megaease/easegress/v2/pkg/context" + "github.com/megaease/easegress/v2/pkg/object/httpserver/routers" "github.com/megaease/easegress/v2/pkg/protocols/httpprot" "github.com/stretchr/testify/assert" gwapis "sigs.k8s.io/gateway-api/apis/v1beta1" ) +type fakeMuxPath struct { + routers.Path +} + +func (mp *fakeMuxPath) Rewrite(context *routers.RouteContext) {} + func TestSpecValidate(t *testing.T) { tests := []struct { name string @@ -123,7 +130,7 @@ func TestSpecValidate(t *testing.T) { }, }, expectErr: true, - errMsg: "invalid path of Redirector, pathPrefix can't be empty", + errMsg: "invalid path of Redirector, replacePrefixMatch can't be empty", }, } @@ -169,7 +176,6 @@ func TestRedirectorHandle2(t *testing.T) { name: "Redirect prefix", reqURL: "http://localhost/user/data/profile", spec: &Spec{ - PathPrefix: new(string), HTTPRequestRedirectFilter: gwapis.HTTPRequestRedirectFilter{ Path: &gwapis.HTTPPathModifier{ Type: gwapis.PrefixMatchHTTPPathModifier, @@ -232,13 +238,15 @@ func TestRedirectorHandle2(t *testing.T) { req, _ := httpprot.NewRequest(stdReq) ctx := context.New(nil) ctx.SetInputRequest(req) + ctx.SetRoute(&fakeMuxPath{ + Path: routers.Path{PathPrefix: "/user/"}, + }) if tt.spec.Path != nil && tt.spec.Path.ReplaceFullPath != nil { *tt.spec.Path.ReplaceFullPath = "/newpath" } if tt.spec.Path != nil && tt.spec.Path.ReplacePrefixMatch != nil { - *tt.spec.PathPrefix = "/user/" *tt.spec.Path.ReplacePrefixMatch = "/account/" } diff --git a/pkg/object/httpserver/mux.go b/pkg/object/httpserver/mux.go index 87e62e53ed..47283a15c3 100644 --- a/pkg/object/httpserver/mux.go +++ b/pkg/object/httpserver/mux.go @@ -129,7 +129,8 @@ func (mi *muxInstance) putRouteToCache(req *httpprot.Request, rc *cachedRoute) { } func newMux(httpStat *httpstat.HTTPStat, topN *httpstat.TopN, - metrics *metrics, mapper context.MuxMapper) *mux { + metrics *metrics, mapper context.MuxMapper, +) *mux { m := &mux{ httpStat: httpStat, topN: topN, @@ -267,6 +268,8 @@ func (mi *muxInstance) serveHTTP(stdw http.ResponseWriter, stdr *http.Request) { routeCtx := routers.NewContext(req) route := mi.search(routeCtx) + ctx.SetRoute(route.route) + var respHeader http.Header defer func() { diff --git a/pkg/object/httpserver/routers/routers.go b/pkg/object/httpserver/routers/routers.go index c3e1d6131f..e1a6edd901 100644 --- a/pkg/object/httpserver/routers/routers.go +++ b/pkg/object/httpserver/routers/routers.go @@ -55,6 +55,16 @@ type ( GetBackend() string // GetClientMaxBodySize is used to get the clientMaxBodySize corresponding to the route. GetClientMaxBodySize() int64 + + // NOTE: Currently we only support path information in readonly. + // Without further requirements, we choose not to expose too much information. + + // GetExactPath is used to get the exact path corresponding to the route. + GetExactPath() string + // GetPathPrefix is used to get the path prefix corresponding to the route. + GetPathPrefix() string + // GetPathRegexp is used to get the path regexp corresponding to the route. + GetPathRegexp() string } // Params are used to store the variables in the search path and their corresponding values. diff --git a/pkg/object/httpserver/routers/spec.go b/pkg/object/httpserver/routers/spec.go index 1647df72bc..8799cbeab7 100644 --- a/pkg/object/httpserver/routers/spec.go +++ b/pkg/object/httpserver/routers/spec.go @@ -252,6 +252,21 @@ func (p *Path) GetClientMaxBodySize() int64 { return p.ClientMaxBodySize } +// GetExactPath returns the exact path of the route. +func (p *Path) GetExactPath() string { + return p.Path +} + +// GetPathPrefix returns the path prefix of the route. +func (p *Path) GetPathPrefix() string { + return p.PathPrefix +} + +// GetPathRegexp returns the path regexp of the route. +func (p *Path) GetPathRegexp() string { + return p.PathRegexp +} + func (hs Headers) init() { for _, h := range hs { if h.Regexp != "" {