Skip to content

Check if (r *Response).Writer is http.Flusher before calling Flush#2017

Closed
MarkRosemaker wants to merge 1 commit intolabstack:masterfrom
MarkRosemaker:check-if-response-writer-is-flusher-before-flushing
Closed

Check if (r *Response).Writer is http.Flusher before calling Flush#2017
MarkRosemaker wants to merge 1 commit intolabstack:masterfrom
MarkRosemaker:check-if-response-writer-is-flusher-before-flushing

Conversation

@MarkRosemaker
Copy link

@MarkRosemaker MarkRosemaker commented Nov 3, 2021

There is no guarantee that the writer is a flusher. In fact, I noticed this issue because a service of a company I work for has paniced because it wasn't:

[PANIC RECOVER] interface conversion: *http.timeoutWriter is not http.Flusher: missing method Flush goroutine 4811 [running]:
github.com/labstack/echo/v4/middleware.RecoverWithConfig.func1.1.1()
	/go/src/service/vendor/github.com/labstack/echo/v4/middleware/recover.go:77 +0x10d
panic({0xec1320, 0xc000266b10})
	/usr/local/go/src/runtime/panic.go:1038 +0x215
github.com/getsentry/sentry-go/echo.(*handler).recoverWithSentry(0xc000481350, 0x7fa2a6, 0xc00074ca00)
	/go/src/service/vendor/github.com/getsentry/sentry-go/echo/sentryecho.go:69 +0xf0
panic({0xec1320, 0xc000266b10})
	/usr/local/go/src/runtime/panic.go:1038 +0x215
github.com/labstack/echo/v4.(*Response).Flush(0x40ac5d)
	/go/src/service/vendor/github.com/labstack/echo/v4/response.go:87 +0x2d
github.com/labstack/echo/v4.(*Response).Flush(0x40ac5d)
	/go/src/service/vendor/github.com/labstack/echo/v4/response.go:87 +0x38
github.com/labstack/echo/v4.(*Response).Flush(0x7e51)
	/go/src/service/vendor/github.com/labstack/echo/v4/response.go:87 +0x38
github.com/labstack/echo/v4.(*Response).Flush(0xc00062c8a0)
	/go/src/service/vendor/github.com/labstack/echo/v4/response.go:87 +0x38
net/http/httputil.(*maxLatencyWriter).Write(0xc000266ae0, {0xc000312000, 0x8000, 0x8000})
	/usr/local/go/src/net/http/httputil/reverseproxy.go:513 +0x1dc
net/http/httputil.(*ReverseProxy).copyBuffer(0x9d5f82, {0x1241da0, 0xc000266ae0}, {0x1241b40, 0xc0002b78c0}, {0x0, 0x0, 0x600000000000000})
	/usr/local/go/src/net/http/httputil/reverseproxy.go:466 +0x217
net/http/httputil.(*ReverseProxy).copyResponse(0xc00026d348, {0x1240aa0, 0xc00062c8a0}, {0x1241b40, 0xc0002b78c0}, 0xffffffffffffffff)
	/usr/local/go/src/net/http/httputil/reverseproxy.go:449 +0x2d0
net/http/httputil.(*ReverseProxy).ServeHTTP(0xc00026d348, {0x12501d0, 0xc00062c8a0}, 0xc00074ca00)
	/usr/local/go/src/net/http/httputil/reverseproxy.go:338 +0xc65

@MarkRosemaker MarkRosemaker changed the title Update response.go Check if (r *Response).Writer is http.Flusher before calling Flush Nov 3, 2021
@aldas
Copy link
Contributor

aldas commented Nov 14, 2021

@MarkRosemaker could you describe a little how this Response is created. I assume it is not standard http.response or writer instance, something is doing some wrapping to Writer before Response is passed to ReverseProxy? You do not happen to have similar ResponseWriter like BodyDump has

func (w *bodyDumpResponseWriter) Write(b []byte) (int, error) {
but without Flush method?

@MarkRosemaker
Copy link
Author

@MarkRosemaker could you describe a little how this Response is created. I assume it is not standard http.response or writer instance, something is doing some wrapping to Writer before Response is passed to ReverseProxy? You do not happen to have similar ResponseWriter like BodyDump has

func (w *bodyDumpResponseWriter) Write(b []byte) (int, error) {

but without Flush method?

Thanks for the reply, @aldas ! It seems to me the response was set via SetResponse in one of our middlewares. The response was wrapped in another object that updates our metrics as well as doing what the initial response does.

@aldas
Copy link
Contributor

aldas commented Nov 15, 2021

Could you check in debugger view what type *echo.Response.Writer field value is (struct type at the moment not interface) and check if that type originates from your application or some some 3rd party library?

@MarkRosemaker
Copy link
Author

Could you check in debugger view what type *echo.Response.Writer field value is (struct type at the moment not interface) and check if that type originates from your application or some some 3rd party library?

Most likely, from what I could find out, it is a struct of our own (the one mentioned above). I've made another PR in one of our repos to implement the Flush method in that one.

I think we just did not consider that echo expects the writer to be a http.Flusher because it's a http.ResponseWriter, not both.

@MarkRosemaker MarkRosemaker deleted the check-if-response-writer-is-flusher-before-flushing branch January 12, 2022 16:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants