api/handler: use http.MaxBytesReader and buffer pool (#1415)

* api/handler: use http.MaxBytesReader

protect api handlers from OOM cases

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
This commit is contained in:
2020-03-26 14:29:28 +03:00
committed by GitHub
parent 776a7d6cd6
commit 02839cfba5
9 changed files with 146 additions and 51 deletions

View File

@@ -24,6 +24,12 @@ const (
// API handler is the default handler which takes api.Request and returns api.Response
func (a *apiHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
bsize := handler.DefaultMaxRecvSize
if a.opts.MaxRecvSize > 0 {
bsize = a.opts.MaxRecvSize
}
r.Body = http.MaxBytesReader(w, r.Body, bsize)
request, err := requestToProto(r)
if err != nil {
er := errors.InternalServerError("go.micro.api", err.Error())

View File

@@ -2,7 +2,6 @@ package api
import (
"fmt"
"io/ioutil"
"mime"
"net"
"net/http"
@@ -11,6 +10,12 @@ import (
api "github.com/micro/go-micro/v2/api/proto"
"github.com/micro/go-micro/v2/client/selector"
"github.com/micro/go-micro/v2/registry"
"github.com/oxtoacart/bpool"
)
var (
// need to calculate later to specify useful defaults
bufferPool = bpool.NewSizedBufferPool(1024, 8)
)
func requestToProto(r *http.Request) (*api.Request, error) {
@@ -39,9 +44,12 @@ func requestToProto(r *http.Request) (*api.Request, error) {
case "application/x-www-form-urlencoded":
// expect form vals in Post data
default:
data, _ := ioutil.ReadAll(r.Body)
req.Body = string(data)
buf := bufferPool.Get()
defer bufferPool.Put(buf)
if _, err = buf.ReadFrom(r.Body); err != nil {
return nil, err
}
req.Body = buf.String()
}
}