diff --git a/context/http.go b/context/http.go index 97b1067f..2cb1d041 100644 --- a/context/http.go +++ b/context/http.go @@ -352,3 +352,13 @@ func (irw *instrumentedResponseWriter) Value(key interface{}) interface{} { fallback: return irw.Context.Value(key) } + +func (irw *instrumentedResponseWriterCN) Value(key interface{}) interface{} { + if keyStr, ok := key.(string); ok { + if keyStr == "http.response" { + return irw + } + } + + return irw.instrumentedResponseWriter.Value(key) +} diff --git a/registry/handlers/api_test.go b/registry/handlers/api_test.go index 99168220..e351cb95 100644 --- a/registry/handlers/api_test.go +++ b/registry/handlers/api_test.go @@ -1460,3 +1460,31 @@ func TestRegistryAsCacheMutationAPIs(t *testing.T) { checkResponse(t, "deleting blob from cache", resp, errcode.ErrorCodeUnsupported.Descriptor().HTTPStatusCode) } + +// TestCheckContextNotifier makes sure the API endpoints get a ResponseWriter +// that implements http.ContextNotifier. +func TestCheckContextNotifier(t *testing.T) { + env := newTestEnv(t, false) + + // Register a new endpoint for testing + env.app.router.Handle("/unittest/{name}/", env.app.dispatcher(func(ctx *Context, r *http.Request) http.Handler { + return handlers.MethodHandler{ + "GET": http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if _, ok := w.(http.CloseNotifier); !ok { + t.Fatal("could not cast ResponseWriter to CloseNotifier") + } + w.WriteHeader(200) + }), + } + })) + + resp, err := http.Get(env.server.URL + "/unittest/reponame/") + if err != nil { + t.Fatalf("unexpected error issuing request: %v", err) + } + defer resp.Body.Close() + + if resp.StatusCode != 200 { + t.Fatalf("wrong status code - expected 200, got %d", resp.StatusCode) + } +} diff --git a/registry/handlers/helpers.go b/registry/handlers/helpers.go index a4f3abcc..5a3c9984 100644 --- a/registry/handlers/helpers.go +++ b/registry/handlers/helpers.go @@ -29,7 +29,7 @@ func copyFullPayload(responseWriter http.ResponseWriter, r *http.Request, destWr if notifier, ok := responseWriter.(http.CloseNotifier); ok { clientClosed = notifier.CloseNotify() } else { - ctxu.GetLogger(context).Warn("the ResponseWriter does not implement CloseNotifier") + ctxu.GetLogger(context).Warnf("the ResponseWriter does not implement CloseNotifier (type: %T)", responseWriter) } // Read in the data, if any.