From 802348ceddbbe4586d2f6d7f904fe7367aa62f22 Mon Sep 17 00:00:00 2001 From: "Gerasimos (Makis) Maropoulos" Date: Sat, 25 Jul 2020 09:23:34 +0300 Subject: [PATCH] fix https://github.com/kataras/iris/issues/1569#issuecomment-663739177 Former-commit-id: c55f1023f4d93f6712c7fa4d299bcf1098872ecf --- HISTORY.md | 2 + .../routing/http-errors/reset-body/main.go | 42 +++++++++++++++++++ .../http-errors/reset-body/main_test.go | 14 +++++++ context/context.go | 6 ++- core/router/handler.go | 5 +++ 5 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 _examples/routing/http-errors/reset-body/main.go create mode 100644 _examples/routing/http-errors/reset-body/main_test.go diff --git a/HISTORY.md b/HISTORY.md index f6101ba4c4..f517654afa 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -371,6 +371,8 @@ Other Improvements: ![DBUG routes](https://iris-go.com/images/v12.2.0-dbug2.png?v=0) +- Fix [#1569#issuecomment-663739177](https://github.com/kataras/iris/issues/1569#issuecomment-663739177). + - Fix [#1564](https://github.com/kataras/iris/issues/1564). - Fix [#1553](https://github.com/kataras/iris/issues/1553). diff --git a/_examples/routing/http-errors/reset-body/main.go b/_examples/routing/http-errors/reset-body/main.go new file mode 100644 index 0000000000..f00de10258 --- /dev/null +++ b/_examples/routing/http-errors/reset-body/main.go @@ -0,0 +1,42 @@ +package main + +import ( + "fmt" + + "github.com/kataras/iris/v12" +) + +func main() { + app := newApp() + app.Listen(":8080") +} + +func newApp() *iris.Application { + app := iris.New() + app.Use(iris.Compression) + + app.OnAnyErrorCode(onErrorCode) + app.Get("/", handler) + + app.Configure(iris.WithResetOnFireErrorCode) + return app +} + +// This is the default error handler Iris uses for any error codes. +func onErrorCode(ctx iris.Context) { + if err := ctx.GetErr(); err != nil { + ctx.WriteString(err.Error()) + } else { + ctx.WriteString(iris.StatusText(ctx.GetStatusCode())) + } +} + +func handler(ctx iris.Context) { + ctx.Record() + + ctx.WriteString("This should NOT be written") + + // [....something bad happened after we "write"] + err := fmt.Errorf("custom error") + ctx.StopWithError(iris.StatusBadRequest, err) +} diff --git a/_examples/routing/http-errors/reset-body/main_test.go b/_examples/routing/http-errors/reset-body/main_test.go new file mode 100644 index 0000000000..3218213e15 --- /dev/null +++ b/_examples/routing/http-errors/reset-body/main_test.go @@ -0,0 +1,14 @@ +package main + +import ( + "testing" + + "github.com/kataras/iris/v12/httptest" +) + +func TestResetCompressionAndFireError(t *testing.T) { // #1569 + app := newApp() + + e := httptest.New(t, app) + e.GET("/").Expect().Status(httptest.StatusBadRequest).Body().Equal("custom error") +} diff --git a/context/context.go b/context/context.go index 8e2ba05470..58e5ea5a26 100644 --- a/context/context.go +++ b/context/context.go @@ -600,6 +600,7 @@ func (ctx *Context) StopWithText(statusCode int, plainText string) { // StopWithError stops the handlers chain and writes the "statusCode" // among with the error "err". +// It Calls the `SetErr` method so error handlers can access the given error. // // If the status code is a failure one then // it will also fire the specified error code handler. @@ -608,6 +609,7 @@ func (ctx *Context) StopWithError(statusCode int, err error) { return } + ctx.SetErr(err) ctx.StopWithText(statusCode, err.Error()) } @@ -4255,7 +4257,9 @@ func (ctx *Context) MaxAge() int64 { // which can be used to reset the body, reset headers, get the body, // get & set the status code at any time and more. func (ctx *Context) Record() { - if w, ok := ctx.writer.(*responseWriter); ok { + switch w := ctx.writer.(type) { + case *ResponseRecorder: + default: recorder := AcquireResponseRecorder() recorder.BeginRecord(w) ctx.ResetResponseWriter(recorder) diff --git a/core/router/handler.go b/core/router/handler.go index 35a790bab9..12d42e35de 100644 --- a/core/router/handler.go +++ b/core/router/handler.go @@ -473,6 +473,11 @@ func (h *routerHandler) FireErrorCode(ctx *context.Context) { // reset if previous content and it's recorder, keep the status code. w.ClearHeaders() w.ResetBody() + + if cw, ok := w.ResponseWriter.(*context.CompressResponseWriter); ok { + // recorder wraps a compress writer. + cw.Disabled = true + } } else if w, ok := ctx.ResponseWriter().(*context.CompressResponseWriter); ok { // reset and disable the gzip in order to be an expected form of http error result w.Disabled = true