From 946a42c021f3688ca411315b71fe989152df7f27 Mon Sep 17 00:00:00 2001 From: Chenrui <631807682@qq.com> Date: Wed, 8 Jul 2020 17:14:52 +0800 Subject: [PATCH 1/3] fix: response http 413 when body size larger then MaxMemory. --- router.go | 4 ++++ router_test.go | 29 +++++++++++++++++++++++++---- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/router.go b/router.go index e71366b4..9b257391 100644 --- a/router.go +++ b/router.go @@ -707,6 +707,10 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request) if r.Method != http.MethodGet && r.Method != http.MethodHead { if BConfig.CopyRequestBody && !context.Input.IsUpload() { + if r.ContentLength > BConfig.MaxMemory { + exception("413", context) + goto Admin + } context.Input.CopyBody(BConfig.MaxMemory) } context.Input.ParseFormOrMulitForm(BConfig.MaxMemory) diff --git a/router_test.go b/router_test.go index 2797b33a..e49f38db 100644 --- a/router_test.go +++ b/router_test.go @@ -15,6 +15,7 @@ package beego import ( + "bytes" "net/http" "net/http/httptest" "strings" @@ -71,7 +72,6 @@ func (tc *TestController) GetEmptyBody() { tc.Ctx.Output.Body(res) } - type JSONController struct { Controller } @@ -656,17 +656,14 @@ func beegoBeforeRouter1(ctx *context.Context) { ctx.WriteString("|BeforeRouter1") } - func beegoBeforeExec1(ctx *context.Context) { ctx.WriteString("|BeforeExec1") } - func beegoAfterExec1(ctx *context.Context) { ctx.WriteString("|AfterExec1") } - func beegoFinishRouter1(ctx *context.Context) { ctx.WriteString("|FinishRouter1") } @@ -709,3 +706,27 @@ func TestYAMLPrepare(t *testing.T) { t.Errorf(w.Body.String()) } } + +func TestRouterEntityTooLargeCopyBody(t *testing.T) { + _MaxMemory := BConfig.MaxMemory + _CopyRequestBody := BConfig.CopyRequestBody + BConfig.CopyRequestBody = true + BConfig.MaxMemory = 20 + + b := bytes.NewBuffer([]byte("barbarbarbarbarbarbarbarbarbar")) + r, _ := http.NewRequest("POST", "/user/123", b) + w := httptest.NewRecorder() + + handler := NewControllerRegister() + handler.Post("/user/:id", func(ctx *context.Context) { + ctx.Output.Body([]byte(ctx.Input.Param(":id"))) + }) + handler.ServeHTTP(w, r) + + BConfig.CopyRequestBody = _CopyRequestBody + BConfig.MaxMemory = _MaxMemory + + if w.Code != 413 { + t.Errorf("TestRouterRequestEntityTooLarge can't run") + } +} From 03f78b2e4a5353173d96cbfbe19a3195cdc032f4 Mon Sep 17 00:00:00 2001 From: Chenrui <631807682@qq.com> Date: Wed, 8 Jul 2020 18:09:01 +0800 Subject: [PATCH 2/3] fix: add error code support --- error.go | 15 ++++++++++++++- hooks.go | 1 + 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/error.go b/error.go index e5e9fd47..0b148974 100644 --- a/error.go +++ b/error.go @@ -28,7 +28,7 @@ import ( ) const ( - errorTypeHandler = iota + errorTypeHandler = iota errorTypeController ) @@ -359,6 +359,19 @@ func gatewayTimeout(rw http.ResponseWriter, r *http.Request) { ) } +// show 413 Payload Too Large +func payloadTooLarge(rw http.ResponseWriter, r *http.Request) { + responseError(rw, r, + 413, + "
The page you have requested is unavailable."+ + "
Perhaps you are here because:"+ + "

", + ) +} + func responseError(rw http.ResponseWriter, r *http.Request, errCode int, errContent string) { t, _ := template.New("beegoerrortemp").Parse(errtpl) data := M{ diff --git a/hooks.go b/hooks.go index b8671d35..49c42d5a 100644 --- a/hooks.go +++ b/hooks.go @@ -34,6 +34,7 @@ func registerDefaultErrorHandler() error { "504": gatewayTimeout, "417": invalidxsrf, "422": missingxsrf, + "413": payloadTooLarge, } for e, h := range m { if _, ok := ErrorMaps[e]; !ok { From c3f14a0ad6ee54f0e474a220a8eb81a67a6b6335 Mon Sep 17 00:00:00 2001 From: Chenrui <631807682@qq.com> Date: Thu, 9 Jul 2020 09:45:40 +0800 Subject: [PATCH 3/3] refactor: log error when payload too large --- error.go | 13 +++++++------ router.go | 2 ++ router_test.go | 2 +- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/error.go b/error.go index 0b148974..f268f723 100644 --- a/error.go +++ b/error.go @@ -363,12 +363,13 @@ func gatewayTimeout(rw http.ResponseWriter, r *http.Request) { func payloadTooLarge(rw http.ResponseWriter, r *http.Request) { responseError(rw, r, 413, - "
The page you have requested is unavailable."+ - "
Perhaps you are here because:"+ - "

", + `
The page you have requested is unavailable. +
Perhaps you are here because:

+ + `, ) } diff --git a/router.go b/router.go index 9b257391..d910deb0 100644 --- a/router.go +++ b/router.go @@ -707,7 +707,9 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request) if r.Method != http.MethodGet && r.Method != http.MethodHead { if BConfig.CopyRequestBody && !context.Input.IsUpload() { + // connection will close if the incoming data are larger (RFC 7231, 6.5.11) if r.ContentLength > BConfig.MaxMemory { + logs.Error(errors.New("payload too large")) exception("413", context) goto Admin } diff --git a/router_test.go b/router_test.go index e49f38db..8ec7927a 100644 --- a/router_test.go +++ b/router_test.go @@ -726,7 +726,7 @@ func TestRouterEntityTooLargeCopyBody(t *testing.T) { BConfig.CopyRequestBody = _CopyRequestBody BConfig.MaxMemory = _MaxMemory - if w.Code != 413 { + if w.Code != http.StatusRequestEntityTooLarge { t.Errorf("TestRouterRequestEntityTooLarge can't run") } }