Go の http パッケージの Request.Body
はこれまで最大バイト数を指定できなかったので、巨大なファイルをアップロードするといった DoS 攻撃を心配するのであれば、各ハンドラの中で独自でサイズ制限しながら読み込む必要がありました。Go 1.18 から http.MaxBytesHandler
が入ったので簡単にサイズ制限をする事ができる様になりました。
MaxBytesHandler は http.Handler
として提供されるので、例えば labstack/echo であれば以下の様に、各ハンドラを直接修正する事なく、簡単に導入して使う事ができます。
package main
import (
"encoding/json"
"fmt"
"net/http"
"github.com/labstack/echo/v4"
)
func middleware(next http.Handler) http.Handler {
// MaxBytesHandler で wrap する
return http.MaxBytesHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
next.ServeHTTP(w, r)
}), 4096)
}
func main() {
e := echo.New()
// ココ
e.Use(echo.WrapMiddleware(middleware))
e.GET("/", func(c echo.Context) error {
return c.String(http.StatusOK, "")
})
e.POST("/", func(c echo.Context) error {
var v interface{}
err := json.NewDecoder(c.Request().Body).Decode(&v)
if err != nil {
return err
}
fmt.Println(v)
return c.String(http.StatusOK, "")
})
e.Logger.Fatal(e.Start(":8989"))
}
試しに大きな JSON を POST すると、500 エラーが返りました。イイカンジです。
$ curl -i -X POST -H "Content-Type: application/json" -d @bar.json http://127.0.0.1:8989/
HTTP/1.1 100 Continue
HTTP/1.1 500 Internal Server Error
Content-Type: application/json; charset=UTF-8
Date: Thu, 23 Dec 2021 15:55:30 GMT
Content-Length: 36
Connection: close
{"message":"Internal Server Error"}