2021/12/24

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"}
Posted at 01:01 | WriteBacks () | Edit
Edit this entry...

wikieditish message: Ready to edit this entry.






















A quick preview will be rendered here when you click "Preview" button.