diff --git a/oapi_validate.go b/oapi_validate.go index f48ad69..bc31e1c 100644 --- a/oapi_validate.go +++ b/oapi_validate.go @@ -136,10 +136,13 @@ func ValidateRequestFromContext(ctx echo.Context, router routers.Router, options clone := req.Clone(req.Context()) clone.URL.Path = strings.TrimPrefix(clone.URL.Path, options.Prefix) req = clone + defer func() { + ctx.Request().Body = clone.Body + ctx.Request().GetBody = clone.GetBody + }() } route, pathParams, err := router.FindRoute(req) - // We failed to find a matching route for the request. if err != nil { if errors.Is(err, routers.ErrMethodNotAllowed) { diff --git a/oapi_validate_test.go b/oapi_validate_test.go index 14a8fed..f80cc32 100644 --- a/oapi_validate_test.go +++ b/oapi_validate_test.go @@ -190,7 +190,6 @@ func TestOapiRequestValidator(t *testing.T) { e.GET("/protected_resource", func(c echo.Context) error { called = true return c.NoContent(http.StatusNoContent) - }) // Call a protected function to which we have access @@ -453,6 +452,10 @@ func TestOapiRequestValidatorWithPrefix(t *testing.T) { called := false + type testBody struct { + Msg string + } + // Register handler under the prefixed path (as echo sees it) e.GET("/api/resource", func(c echo.Context) error { called = true @@ -460,6 +463,16 @@ func TestOapiRequestValidatorWithPrefix(t *testing.T) { assert.Equal(t, "/api/resource", c.Request().URL.Path) return c.NoContent(http.StatusOK) }) + e.POST("/api/resource", func(c echo.Context) error { + called = true + // The original request path should be preserved for the handler + assert.Equal(t, "/api/resource", c.Request().URL.Path) + req := c.Request() + data, err := io.ReadAll(req.Body) + require.NoError(t, err, "Reading POST body") + assert.Equal(t, "{\"Msg\":\"testbody\"}", string(data)) + return c.NoContent(http.StatusOK) + }) // A request to /api/resource should validate against /resource in the spec { @@ -469,6 +482,16 @@ func TestOapiRequestValidatorWithPrefix(t *testing.T) { called = false } + // A POST request to /api/resource should validate against /resource in the spec and have a specific body + { + rec := doPost(t, e, "http://test.hostname/api/resource", testBody{ + Msg: "testbody", + }) + assert.Equal(t, http.StatusOK, rec.Code) + assert.True(t, called, "Handler should have been called") + called = false + } + // A request with query params should also validate correctly { rec := doGet(t, e, "http://test.hostname/api/resource?id=50") @@ -566,7 +589,6 @@ func TestEncodedPathParams(t *testing.T) { } func TestGetSkipperFromOptions(t *testing.T) { - options := new(Options) assert.NotNil(t, getSkipperFromOptions(options))