Merge pull request #830 from aaronlehmann/no-closenotifier-panic
Don't panic when a http.ResponseWriter does not implement CloseNotifier
This commit is contained in:
commit
ec77b836dd
3 changed files with 22 additions and 17 deletions
|
@ -103,17 +103,21 @@ func GetRequestID(ctx Context) string {
|
||||||
// WithResponseWriter returns a new context and response writer that makes
|
// WithResponseWriter returns a new context and response writer that makes
|
||||||
// interesting response statistics available within the context.
|
// interesting response statistics available within the context.
|
||||||
func WithResponseWriter(ctx Context, w http.ResponseWriter) (Context, http.ResponseWriter) {
|
func WithResponseWriter(ctx Context, w http.ResponseWriter) (Context, http.ResponseWriter) {
|
||||||
closeNotifier, ok := w.(http.CloseNotifier)
|
irw := instrumentedResponseWriter{
|
||||||
if !ok {
|
|
||||||
panic("the ResponseWriter does not implement CloseNotifier")
|
|
||||||
}
|
|
||||||
irw := &instrumentedResponseWriter{
|
|
||||||
ResponseWriter: w,
|
ResponseWriter: w,
|
||||||
CloseNotifier: closeNotifier,
|
|
||||||
Context: ctx,
|
Context: ctx,
|
||||||
}
|
}
|
||||||
|
|
||||||
return irw, irw
|
if closeNotifier, ok := w.(http.CloseNotifier); ok {
|
||||||
|
irwCN := &instrumentedResponseWriterCN{
|
||||||
|
instrumentedResponseWriter: irw,
|
||||||
|
CloseNotifier: closeNotifier,
|
||||||
|
}
|
||||||
|
|
||||||
|
return irwCN, irwCN
|
||||||
|
}
|
||||||
|
|
||||||
|
return &irw, &irw
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetResponseWriter returns the http.ResponseWriter from the provided
|
// GetResponseWriter returns the http.ResponseWriter from the provided
|
||||||
|
@ -263,11 +267,19 @@ func (ctx *muxVarsContext) Value(key interface{}) interface{} {
|
||||||
return ctx.Context.Value(key)
|
return ctx.Context.Value(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// instrumentedResponseWriterCN provides response writer information in a
|
||||||
|
// context. It implements http.CloseNotifier so that users can detect
|
||||||
|
// early disconnects.
|
||||||
|
type instrumentedResponseWriterCN struct {
|
||||||
|
instrumentedResponseWriter
|
||||||
|
http.CloseNotifier
|
||||||
|
}
|
||||||
|
|
||||||
// instrumentedResponseWriter provides response writer information in a
|
// instrumentedResponseWriter provides response writer information in a
|
||||||
// context.
|
// context. This variant is only used in the case where CloseNotifier is not
|
||||||
|
// implemented by the parent ResponseWriter.
|
||||||
type instrumentedResponseWriter struct {
|
type instrumentedResponseWriter struct {
|
||||||
http.ResponseWriter
|
http.ResponseWriter
|
||||||
http.CloseNotifier
|
|
||||||
Context
|
Context
|
||||||
|
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
|
|
|
@ -110,13 +110,6 @@ func (trw *testResponseWriter) Header() http.Header {
|
||||||
return trw.header
|
return trw.header
|
||||||
}
|
}
|
||||||
|
|
||||||
// CloseNotify is only here to make the testResponseWriter implement the
|
|
||||||
// http.CloseNotifier interface, which WithResponseWriter expects to be
|
|
||||||
// implemented.
|
|
||||||
func (trw *testResponseWriter) CloseNotify() <-chan bool {
|
|
||||||
return make(chan bool)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (trw *testResponseWriter) Write(p []byte) (n int, err error) {
|
func (trw *testResponseWriter) Write(p []byte) (n int, err error) {
|
||||||
if trw.status == 0 {
|
if trw.status == 0 {
|
||||||
trw.status = http.StatusOK
|
trw.status = http.StatusOK
|
||||||
|
|
|
@ -29,7 +29,7 @@ func copyFullPayload(responseWriter http.ResponseWriter, r *http.Request, destWr
|
||||||
if notifier, ok := responseWriter.(http.CloseNotifier); ok {
|
if notifier, ok := responseWriter.(http.CloseNotifier); ok {
|
||||||
clientClosed = notifier.CloseNotify()
|
clientClosed = notifier.CloseNotify()
|
||||||
} else {
|
} else {
|
||||||
panic("the ResponseWriter does not implement CloseNotifier")
|
ctxu.GetLogger(context).Warn("the ResponseWriter does not implement CloseNotifier")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read in the data, if any.
|
// Read in the data, if any.
|
||||||
|
|
Loading…
Reference in a new issue