diff --git a/ocis-pkg/middleware/query_unescape.go b/ocis-pkg/middleware/query_unescape.go new file mode 100644 index 00000000000..0bde1155c82 --- /dev/null +++ b/ocis-pkg/middleware/query_unescape.go @@ -0,0 +1,30 @@ +package middleware + +import ( + "net/http" + "net/url" + + "github.com/go-chi/chi/v5" +) + +// QueryUnescape is a middleware that unescapes the raw path of the request. +func QueryUnescape(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + rctx := chi.RouteContext(r.Context()) + routePath := rctx.RoutePath + + if routePath == "" { + if r.URL.RawPath != "" { + routePath = r.URL.RawPath + } else { + routePath = r.URL.Path + } + + if decodedRoutePath, err := url.QueryUnescape(routePath); err == nil { + rctx.RoutePath = decodedRoutePath + } + } + + next.ServeHTTP(w, r) + }) +} diff --git a/ocis-pkg/middleware/query_unescape_test.go b/ocis-pkg/middleware/query_unescape_test.go new file mode 100644 index 00000000000..c0b166a227c --- /dev/null +++ b/ocis-pkg/middleware/query_unescape_test.go @@ -0,0 +1,43 @@ +package middleware_test + +import ( + "context" + "net/http" + "net/http/httptest" + "testing" + + "github.com/go-chi/chi/v5" + . "github.com/onsi/gomega" + + "github.com/owncloud/ocis/v2/ocis-pkg/middleware" +) + +func TestQueryUnescape(t *testing.T) { + tests := []struct { + name string + expected string + }{ + {"/v1.0/1$2!3///users", "/v1.0/1$2!3///users"}, + {"/v1.0/1%242%213///users", "/v1.0/1$2!3///users"}, + {"/v1.0/1%242%213///users?$filter=startswith(givenName,%20%27J%27)", "/v1.0/1$2!3///users"}, + } + + g := NewWithT(t) + + for _, tt := range tests { + tt := tt + + t.Run(tt.name, func(t *testing.T) { + middleware.QueryUnescape(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ctx := chi.RouteContext(r.Context()) + g.Expect(ctx).ToNot(BeNil()) + g.Expect(ctx.RoutePath).To(Equal(tt.expected)) + })). + ServeHTTP( + httptest.NewRecorder(), + httptest.NewRequest("GET", tt.name, nil). + WithContext(context.WithValue(context.Background(), chi.RouteCtxKey, chi.NewRouteContext())), + ) + }) + } +} diff --git a/services/graph/pkg/server/http/server.go b/services/graph/pkg/server/http/server.go index 113ffac6002..01599f8aedf 100644 --- a/services/graph/pkg/server/http/server.go +++ b/services/graph/pkg/server/http/server.go @@ -8,6 +8,10 @@ import ( "github.com/cs3org/reva/v2/pkg/events/stream" "github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool" chimiddleware "github.com/go-chi/chi/v5/middleware" + "github.com/pkg/errors" + "go-micro.dev/v4" + "go-micro.dev/v4/events" + "github.com/owncloud/ocis/v2/ocis-pkg/account" "github.com/owncloud/ocis/v2/ocis-pkg/cors" "github.com/owncloud/ocis/v2/ocis-pkg/keycloak" @@ -21,9 +25,6 @@ import ( settingssvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/settings/v0" graphMiddleware "github.com/owncloud/ocis/v2/services/graph/pkg/middleware" svc "github.com/owncloud/ocis/v2/services/graph/pkg/service/v0" - "github.com/pkg/errors" - "go-micro.dev/v4" - "go-micro.dev/v4/events" ) // Server initializes the http service and server. @@ -62,6 +63,7 @@ func Server(opts ...Option) (http.Service, error) { } middlewares := []func(stdhttp.Handler) stdhttp.Handler{ + middleware.QueryUnescape, middleware.TraceContext, chimiddleware.RequestID, middleware.Version(