Improve context package
You shouldn't have to import both: github.com/docker/distribution/context golang.org/x/net/context just to use the distribution tools and implement the distribution interfaces. By pulling the Context interface from golang.org/x/net/context into the context package within the distribution project, you no longer have to import both packages. Note: You do not have to change anything anywhere else yet! All current uses of both packages together will still work correctly because the Context interface from either package is identical. I've also made some other minor changes: - Added a RemoteIP function. It's like RemoteAddr but discards the port suffix - Added `.String()` to the response duration context value so that JSON log formatting shows human-parseable duration and not just number of nano-seconds - Added WithMapContext(...) to the context package. This is a useful function so I pulled it out of the main.go in cmd/registry so that it can be used elsewhere. Docker-DCO-1.1-Signed-off-by: Josh Hawn <josh.hawn@docker.com> (github: jlhawn)
This commit is contained in:
parent
5052dc692f
commit
731e0b0066
9 changed files with 97 additions and 63 deletions
|
@ -11,7 +11,6 @@ import (
|
|||
"code.google.com/p/go-uuid/uuid"
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/gorilla/mux"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// Common errors used with this package.
|
||||
|
@ -50,12 +49,25 @@ func RemoteAddr(r *http.Request) string {
|
|||
return r.RemoteAddr
|
||||
}
|
||||
|
||||
// RemoteIP extracts the remote IP of the request, taking into
|
||||
// account proxy headers.
|
||||
func RemoteIP(r *http.Request) string {
|
||||
addr := RemoteAddr(r)
|
||||
|
||||
// Try parsing it as "IP:port"
|
||||
if ip, _, err := net.SplitHostPort(addr); err == nil {
|
||||
return ip
|
||||
}
|
||||
|
||||
return addr
|
||||
}
|
||||
|
||||
// WithRequest places the request on the context. The context of the request
|
||||
// is assigned a unique id, available at "http.request.id". The request itself
|
||||
// is available at "http.request". Other common attributes are available under
|
||||
// the prefix "http.request.". If a request is already present on the context,
|
||||
// this method will panic.
|
||||
func WithRequest(ctx context.Context, r *http.Request) context.Context {
|
||||
func WithRequest(ctx Context, r *http.Request) Context {
|
||||
if ctx.Value("http.request") != nil {
|
||||
// NOTE(stevvooe): This needs to be considered a programming error. It
|
||||
// is unlikely that we'd want to have more than one request in
|
||||
|
@ -74,7 +86,7 @@ func WithRequest(ctx context.Context, r *http.Request) context.Context {
|
|||
// GetRequest returns the http request in the given context. Returns
|
||||
// ErrNoRequestContext if the context does not have an http request associated
|
||||
// with it.
|
||||
func GetRequest(ctx context.Context) (*http.Request, error) {
|
||||
func GetRequest(ctx Context) (*http.Request, error) {
|
||||
if r, ok := ctx.Value("http.request").(*http.Request); r != nil && ok {
|
||||
return r, nil
|
||||
}
|
||||
|
@ -83,13 +95,13 @@ func GetRequest(ctx context.Context) (*http.Request, error) {
|
|||
|
||||
// GetRequestID attempts to resolve the current request id, if possible. An
|
||||
// error is return if it is not available on the context.
|
||||
func GetRequestID(ctx context.Context) string {
|
||||
func GetRequestID(ctx Context) string {
|
||||
return GetStringValue(ctx, "http.request.id")
|
||||
}
|
||||
|
||||
// WithResponseWriter returns a new context and response writer that makes
|
||||
// interesting response statistics available within the context.
|
||||
func WithResponseWriter(ctx context.Context, w http.ResponseWriter) (context.Context, http.ResponseWriter) {
|
||||
func WithResponseWriter(ctx Context, w http.ResponseWriter) (Context, http.ResponseWriter) {
|
||||
irw := &instrumentedResponseWriter{
|
||||
ResponseWriter: w,
|
||||
Context: ctx,
|
||||
|
@ -107,7 +119,7 @@ var getVarsFromRequest = mux.Vars
|
|||
// example, if looking for the variable "name", it can be accessed as
|
||||
// "vars.name". Implementations that are accessing values need not know that
|
||||
// the underlying context is implemented with gorilla/mux vars.
|
||||
func WithVars(ctx context.Context, r *http.Request) context.Context {
|
||||
func WithVars(ctx Context, r *http.Request) Context {
|
||||
return &muxVarsContext{
|
||||
Context: ctx,
|
||||
vars: getVarsFromRequest(r),
|
||||
|
@ -117,7 +129,7 @@ func WithVars(ctx context.Context, r *http.Request) context.Context {
|
|||
// GetRequestLogger returns a logger that contains fields from the request in
|
||||
// the current context. If the request is not available in the context, no
|
||||
// fields will display. Request loggers can safely be pushed onto the context.
|
||||
func GetRequestLogger(ctx context.Context) Logger {
|
||||
func GetRequestLogger(ctx Context) Logger {
|
||||
return GetLogger(ctx,
|
||||
"http.request.id",
|
||||
"http.request.method",
|
||||
|
@ -133,7 +145,7 @@ func GetRequestLogger(ctx context.Context) Logger {
|
|||
// Because the values are read at call time, pushing a logger returned from
|
||||
// this function on the context will lead to missing or invalid data. Only
|
||||
// call this at the end of a request, after the response has been written.
|
||||
func GetResponseLogger(ctx context.Context) Logger {
|
||||
func GetResponseLogger(ctx Context) Logger {
|
||||
l := getLogrusLogger(ctx,
|
||||
"http.response.written",
|
||||
"http.response.status",
|
||||
|
@ -142,7 +154,7 @@ func GetResponseLogger(ctx context.Context) Logger {
|
|||
duration := Since(ctx, "http.request.startedat")
|
||||
|
||||
if duration > 0 {
|
||||
l = l.WithField("http.response.duration", duration)
|
||||
l = l.WithField("http.response.duration", duration.String())
|
||||
}
|
||||
|
||||
return l
|
||||
|
@ -150,7 +162,7 @@ func GetResponseLogger(ctx context.Context) Logger {
|
|||
|
||||
// httpRequestContext makes information about a request available to context.
|
||||
type httpRequestContext struct {
|
||||
context.Context
|
||||
Context
|
||||
|
||||
startedAt time.Time
|
||||
id string
|
||||
|
@ -209,7 +221,7 @@ fallback:
|
|||
}
|
||||
|
||||
type muxVarsContext struct {
|
||||
context.Context
|
||||
Context
|
||||
vars map[string]string
|
||||
}
|
||||
|
||||
|
@ -235,7 +247,7 @@ func (ctx *muxVarsContext) Value(key interface{}) interface{} {
|
|||
// context.
|
||||
type instrumentedResponseWriter struct {
|
||||
http.ResponseWriter
|
||||
context.Context
|
||||
Context
|
||||
|
||||
mu sync.Mutex
|
||||
status int
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue