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

@@ -12,7 +12,7 @@ import (
)
type event struct {
options handler.Options
opts handler.Options
}
var (
@@ -58,10 +58,17 @@ func evRoute(ns, p string) (string, string) {
}
func (e *event) ServeHTTP(w http.ResponseWriter, r *http.Request) {
bsize := handler.DefaultMaxRecvSize
if e.opts.MaxRecvSize > 0 {
bsize = e.opts.MaxRecvSize
}
r.Body = http.MaxBytesReader(w, r.Body, bsize)
// request to topic:event
// create event
// publish to topic
topic, _ := evRoute(e.options.Namespace, r.URL.Path)
topic, _ := evRoute(e.opts.Namespace, r.URL.Path)
// create event
ev, err := FromRequest(r)
@@ -71,7 +78,7 @@ func (e *event) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}
// get client
c := e.options.Service.Client()
c := e.opts.Service.Client()
// create publication
p := c.NewMessage(topic, ev)
@@ -89,6 +96,6 @@ func (e *event) String() string {
func NewHandler(opts ...handler.Option) handler.Handler {
return &event{
options: handler.NewOptions(opts...),
opts: handler.NewOptions(opts...),
}
}

View File

@@ -24,7 +24,6 @@ import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"mime"
"net/http"
"strings"
@@ -32,9 +31,14 @@ import (
"unicode"
"github.com/google/uuid"
"github.com/oxtoacart/bpool"
validator "gopkg.in/go-playground/validator.v9"
)
var (
bufferPool = bpool.NewSizedBufferPool(1024, 8)
)
const (
// TransformationVersion is indicative of the revision of how Event Gateway transforms a request into CloudEvents format.
TransformationVersion = "0.1"
@@ -97,10 +101,12 @@ func FromRequest(r *http.Request) (*Event, error) {
// Read request body
body := []byte{}
if r.Body != nil {
body, err = ioutil.ReadAll(r.Body)
if err != nil {
buf := bufferPool.Get()
defer bufferPool.Put(buf)
if _, err := buf.ReadFrom(r.Body); err != nil {
return nil, err
}
body = buf.Bytes()
}
var event *Event