猿问

Go 的 http.MaxBytesReader,为什么要传入 writer?

直观地说,我认为当您创建 MaxByteReader 并传入 http.ResponseWriter 时,它会为您写出状态代码。但事实并非如此,作者实际上在做什么?


例子:


func maxBytesMiddleware(next http.Handler) http.Handler {

    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

        r.Body = http.MaxBytesReader(w, r.Body, 1)


        next.ServeHTTP(w, r)

    })

}


func mainHandler(w http.ResponseWriter, r *http.Request) {

    var i interface{}

    err := json.NewDecoder(r.Body).Decode(&i)

    if err != nil {

        fmt.Println(err.Error())

    }

}


func TestMaxBytesMiddleware(t *testing.T) {

    handlerToTest := maxBytesMiddleware(http.HandlerFunc(mainHandler))


    req := httptest.NewRequest(http.MethodPost, "http://test.com", bytes.NewReader(json.RawMessage(`{"hello":"world"}`)))


    recorder := httptest.NewRecorder()

    handlerToTest.ServeHTTP(recorder, req)


    if recorder.Result().StatusCode != http.StatusRequestEntityTooLarge {

        t.Errorf("expected %d got %d", http.StatusRequestEntityTooLarge, recorder.Result().StatusCode)

    }

}

但是当这个测试运行时,我得到了这个:


http: request body too large

--- FAIL: TestMaxBytesMiddleware (0.00s)

    main_test.go:37: expected 413 got 200

如果我想要我认为这个函数所做的所需功能,我需要将我的 mainHandler 更改为如下所示:


func mainHandler(w http.ResponseWriter, r *http.Request) {

    var i interface{}

    err := json.NewDecoder(r.Body).Decode(&i)

    if err != nil {

        if err.Error() == "http: request body too large" {

            w.WriteHeader(http.StatusRequestEntityTooLarge)

            return

        }


        fmt.Println(err.Error())

    }

}

那么那个作家到底是为了什么?


Cats萌萌
浏览 498回答 1
1回答

拉风的咖菲猫

如果 MaxBytesReader 在读取整个正文之前停止,它会在 writer 上设置一些标志,以确保在发送响应后关闭 HTTP 连接。通常服务器愿意从同一个连接中读取另一个请求(HTTP keepalive),但是如果前一个请求的未读位仍在管道中,它就不能这样做,所以它必须关闭连接,强制客户端如果要发送更多请求,则建立新连接。这是使用私有requestTooLarge方法完成的http.ResponseWriter。
随时随地看视频慕课网APP

相关分类

Go
我要回答