1
0
mirror of https://github.com/pocketbase/pocketbase.git synced 2025-01-10 00:43:36 +02:00
pocketbase/tools/rest/multi_binder.go
2022-07-07 00:19:05 +03:00

60 lines
1.4 KiB
Go

package rest
import (
"bytes"
"encoding/json"
"io"
"net/http"
"strings"
"github.com/labstack/echo/v5"
)
// BindBody binds request body content to i.
//
// This is similar to `echo.BindBody()`, but for JSON requests uses
// custom json reader that **copies** the request body, allowing multiple reads.
func BindBody(c echo.Context, i interface{}) error {
req := c.Request()
if req.ContentLength == 0 {
return nil
}
ctype := req.Header.Get(echo.HeaderContentType)
switch {
case strings.HasPrefix(ctype, echo.MIMEApplicationJSON):
err := ReadJsonBodyCopy(c.Request(), i)
if err != nil {
return echo.NewHTTPErrorWithInternal(http.StatusBadRequest, err, err.Error())
}
return nil
default:
// fallback to the default binder
return echo.BindBody(c, i)
}
}
// ReadJsonBodyCopy reads the request body into i by
// creating a copy of `r.Body` to allow multiple reads.
func ReadJsonBodyCopy(r *http.Request, i interface{}) error {
body := r.Body
// this usually shouldn't be needed because the Server calls close for us
// but we are changing the request body with a new reader
defer body.Close()
limitReader := io.LimitReader(body, DefaultMaxMemory)
bodyBytes, readErr := io.ReadAll(limitReader)
if readErr != nil {
return readErr
}
err := json.NewDecoder(bytes.NewReader(bodyBytes)).Decode(i)
// set new body reader
r.Body = io.NopCloser(bytes.NewReader(bodyBytes))
return err
}