forked from TrueCloudLab/distribution
register/handlers: remove context manager
Signed-off-by: Stephen J Day <stephen.day@docker.com>
This commit is contained in:
parent
a73ed75f5a
commit
1f0a9dbca0
2 changed files with 11 additions and 73 deletions
|
@ -596,24 +596,19 @@ func (app *App) configureSecret(configuration *configuration.Configuration) {
|
||||||
func (app *App) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
func (app *App) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
defer r.Body.Close() // ensure that request body is always closed.
|
defer r.Body.Close() // ensure that request body is always closed.
|
||||||
|
|
||||||
// Instantiate an http context here so we can track the error codes
|
// Prepare the context with our own little decorations.
|
||||||
// returned by the request router.
|
ctx := r.Context()
|
||||||
ctx := defaultContextManager.context(app, w, r)
|
ctx = ctxu.WithRequest(ctx, r)
|
||||||
|
ctx, w = ctxu.WithResponseWriter(ctx, w)
|
||||||
|
ctx = ctxu.WithLogger(ctx, ctxu.GetRequestLogger(ctx))
|
||||||
|
r = r.WithContext(ctx)
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
status, ok := ctx.Value("http.response.status").(int)
|
status, ok := ctx.Value("http.response.status").(int)
|
||||||
if ok && status >= 200 && status <= 399 {
|
if ok && status >= 200 && status <= 399 {
|
||||||
ctxu.GetResponseLogger(ctx).Infof("response completed")
|
ctxu.GetResponseLogger(r.Context()).Infof("response completed")
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
defer defaultContextManager.release(ctx)
|
|
||||||
|
|
||||||
// NOTE(stevvooe): Total hack to get instrumented responsewriter from context.
|
|
||||||
var err error
|
|
||||||
w, err = ctxu.GetResponseWriter(ctx)
|
|
||||||
if err != nil {
|
|
||||||
ctxu.GetLogger(ctx).Warnf("response writer not found in context")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set a header with the Docker Distribution API Version for all responses.
|
// Set a header with the Docker Distribution API Version for all responses.
|
||||||
w.Header().Add("Docker-Distribution-API-Version", "registry/2.0")
|
w.Header().Add("Docker-Distribution-API-Version", "registry/2.0")
|
||||||
|
@ -649,6 +644,9 @@ func (app *App) dispatcher(dispatch dispatchFunc) http.Handler {
|
||||||
// Add username to request logging
|
// Add username to request logging
|
||||||
context.Context = ctxu.WithLogger(context.Context, ctxu.GetLogger(context.Context, auth.UserNameKey))
|
context.Context = ctxu.WithLogger(context.Context, ctxu.GetLogger(context.Context, auth.UserNameKey))
|
||||||
|
|
||||||
|
// sync up context on the request.
|
||||||
|
r = r.WithContext(context)
|
||||||
|
|
||||||
if app.nameRequired(r) {
|
if app.nameRequired(r) {
|
||||||
nameRef, err := reference.WithName(getName(context))
|
nameRef, err := reference.WithName(getName(context))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -756,7 +754,7 @@ func (app *App) logError(context context.Context, errors errcode.Errors) {
|
||||||
// context constructs the context object for the application. This only be
|
// context constructs the context object for the application. This only be
|
||||||
// called once per request.
|
// called once per request.
|
||||||
func (app *App) context(w http.ResponseWriter, r *http.Request) *Context {
|
func (app *App) context(w http.ResponseWriter, r *http.Request) *Context {
|
||||||
ctx := defaultContextManager.context(app, w, r)
|
ctx := r.Context()
|
||||||
ctx = ctxu.WithVars(ctx, r)
|
ctx = ctxu.WithVars(ctx, r)
|
||||||
ctx = ctxu.WithLogger(ctx, ctxu.GetLogger(ctx,
|
ctx = ctxu.WithLogger(ctx, ctxu.GetLogger(ctx,
|
||||||
"vars.name",
|
"vars.name",
|
||||||
|
|
|
@ -3,7 +3,6 @@ package handlers
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/docker/distribution"
|
"github.com/docker/distribution"
|
||||||
ctxu "github.com/docker/distribution/context"
|
ctxu "github.com/docker/distribution/context"
|
||||||
|
@ -91,62 +90,3 @@ func getUserName(ctx context.Context, r *http.Request) string {
|
||||||
|
|
||||||
return username
|
return username
|
||||||
}
|
}
|
||||||
|
|
||||||
// contextManager allows us to associate net/context.Context instances with a
|
|
||||||
// request, based on the memory identity of http.Request. This prepares http-
|
|
||||||
// level context, which is not application specific. If this is called,
|
|
||||||
// (*contextManager).release must be called on the context when the request is
|
|
||||||
// completed.
|
|
||||||
//
|
|
||||||
// Providing this circumvents a lot of necessity for dispatchers with the
|
|
||||||
// benefit of instantiating the request context much earlier.
|
|
||||||
//
|
|
||||||
// TODO(stevvooe): Consider making this facility a part of the context package.
|
|
||||||
type contextManager struct {
|
|
||||||
contexts map[*http.Request]context.Context
|
|
||||||
mu sync.Mutex
|
|
||||||
}
|
|
||||||
|
|
||||||
// defaultContextManager is just a global instance to register request contexts.
|
|
||||||
var defaultContextManager = newContextManager()
|
|
||||||
|
|
||||||
func newContextManager() *contextManager {
|
|
||||||
return &contextManager{
|
|
||||||
contexts: make(map[*http.Request]context.Context),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// context either returns a new context or looks it up in the manager.
|
|
||||||
func (cm *contextManager) context(parent context.Context, w http.ResponseWriter, r *http.Request) context.Context {
|
|
||||||
cm.mu.Lock()
|
|
||||||
defer cm.mu.Unlock()
|
|
||||||
|
|
||||||
ctx, ok := cm.contexts[r]
|
|
||||||
if ok {
|
|
||||||
return ctx
|
|
||||||
}
|
|
||||||
|
|
||||||
if parent == nil {
|
|
||||||
parent = ctxu.Background()
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx = ctxu.WithRequest(parent, r)
|
|
||||||
ctx, w = ctxu.WithResponseWriter(ctx, w)
|
|
||||||
ctx = ctxu.WithLogger(ctx, ctxu.GetRequestLogger(ctx))
|
|
||||||
cm.contexts[r] = ctx
|
|
||||||
|
|
||||||
return ctx
|
|
||||||
}
|
|
||||||
|
|
||||||
// releases frees any associated with resources from request.
|
|
||||||
func (cm *contextManager) release(ctx context.Context) {
|
|
||||||
cm.mu.Lock()
|
|
||||||
defer cm.mu.Unlock()
|
|
||||||
|
|
||||||
r, err := ctxu.GetRequest(ctx)
|
|
||||||
if err != nil {
|
|
||||||
ctxu.GetLogger(ctx).Errorf("no request found in context during release")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
delete(cm.contexts, r)
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue