Summary
While experimenting with echov5, this was observed. Later trying it on echo/v4, the issue could be reproduced.
When Options.Prefix is set, the middleware reads and closes the request body during validation but fails to restore it on the original echo.Context request. Downstream handlers that try to read the body receive http: invalid Read on closed Body or EOF.
Reproduction
package main
import (
"context"
"tryecho/api"
"github.com/labstack/echo/v4"
echomiddleware "github.com/oapi-codegen/echo-middleware"
)
type Server struct{}
func (s *Server) CreateItem(ctx context.Context, request api.CreateItemRequestObject) (api.CreateItemResponseObject, error) {
return api.CreateItem201JSONResponse{
Name: &request.Body.Name,
}, nil
}
func main() {
e := echo.New()
spec, err := api.GetSwagger()
if err != nil {
panic(err)
}
spec.Servers = nil
g := e.Group("/api")
g.Use(echomiddleware.OapiRequestValidatorWithOptions(spec, &echomiddleware.Options{
Prefix: "/api",
}))
myServer := &Server{}
strictHandler := api.NewStrictHandler(myServer, nil)
api.RegisterHandlers(g, strictHandler)
e.Logger.Fatal(e.Start(":8080"))
}
➜ tryecho curl --location 'localhost:8080/api/items' \
--header 'Content-Type: application/json' \
--data '{
"name":""
}'
{"message":"http: invalid Read on closed Body"}
Workaround (until fixed)
Consumers using Prefix must pre-buffer the body themselves so GetBody is set before the middleware runs:
g.Use(func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
req := c.Request()
if req.Body != nil && req.Body != http.NoBody {
data, _ := io.ReadAll(req.Body)
req.Body.Close()
req.GetBody = func() (io.ReadCloser, error) {
return io.NopCloser(bytes.NewReader(data)), nil
}
req.Body, _ = req.GetBody()
}
return next(c)
}
})
g.Use(OapiRequestValidatorWithOptions(spec, &Options{Prefix: "/api"}))
Summary
While experimenting with echov5, this was observed. Later trying it on echo/v4, the issue could be reproduced.
When
Options.Prefixis set, the middleware reads and closes the request body during validation but fails to restore it on the originalecho.Contextrequest. Downstream handlers that try to read the body receivehttp: invalid Read on closed BodyorEOF.Reproduction
Workaround (until fixed)
Consumers using
Prefixmust pre-buffer the body themselves soGetBodyis set before the middleware runs: