github.com/a4a881d4/docker@v1.9.0-rc2/api/server/middleware.go (about) 1 package server 2 3 import ( 4 "net/http" 5 "runtime" 6 "strings" 7 8 "github.com/Sirupsen/logrus" 9 "github.com/docker/docker/api" 10 "github.com/docker/docker/api/server/httputils" 11 "github.com/docker/docker/autogen/dockerversion" 12 "github.com/docker/docker/errors" 13 "github.com/docker/docker/pkg/version" 14 "golang.org/x/net/context" 15 ) 16 17 // middleware is an adapter to allow the use of ordinary functions as Docker API filters. 18 // Any function that has the appropriate signature can be register as a middleware. 19 type middleware func(handler httputils.APIFunc) httputils.APIFunc 20 21 // loggingMiddleware logs each request when logging is enabled. 22 func (s *Server) loggingMiddleware(handler httputils.APIFunc) httputils.APIFunc { 23 return func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { 24 if s.cfg.Logging { 25 logrus.Infof("%s %s", r.Method, r.RequestURI) 26 } 27 return handler(ctx, w, r, vars) 28 } 29 } 30 31 // userAgentMiddleware checks the User-Agent header looking for a valid docker client spec. 32 func (s *Server) userAgentMiddleware(handler httputils.APIFunc) httputils.APIFunc { 33 return func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { 34 if strings.Contains(r.Header.Get("User-Agent"), "Docker-Client/") { 35 dockerVersion := version.Version(s.cfg.Version) 36 37 userAgent := strings.Split(r.Header.Get("User-Agent"), "/") 38 39 // v1.20 onwards includes the GOOS of the client after the version 40 // such as Docker/1.7.0 (linux) 41 if len(userAgent) == 2 && strings.Contains(userAgent[1], " ") { 42 userAgent[1] = strings.Split(userAgent[1], " ")[0] 43 } 44 45 if len(userAgent) == 2 && !dockerVersion.Equal(version.Version(userAgent[1])) { 46 logrus.Debugf("Warning: client and server don't have the same version (client: %s, server: %s)", userAgent[1], dockerVersion) 47 } 48 } 49 return handler(ctx, w, r, vars) 50 } 51 } 52 53 // corsMiddleware sets the CORS header expectations in the server. 54 func (s *Server) corsMiddleware(handler httputils.APIFunc) httputils.APIFunc { 55 return func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { 56 // If "api-cors-header" is not given, but "api-enable-cors" is true, we set cors to "*" 57 // otherwise, all head values will be passed to HTTP handler 58 corsHeaders := s.cfg.CorsHeaders 59 if corsHeaders == "" && s.cfg.EnableCors { 60 corsHeaders = "*" 61 } 62 63 if corsHeaders != "" { 64 writeCorsHeaders(w, r, corsHeaders) 65 } 66 return handler(ctx, w, r, vars) 67 } 68 } 69 70 // versionMiddleware checks the api version requirements before passing the request to the server handler. 71 func versionMiddleware(handler httputils.APIFunc) httputils.APIFunc { 72 return func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { 73 apiVersion := version.Version(vars["version"]) 74 if apiVersion == "" { 75 apiVersion = api.Version 76 } 77 78 if apiVersion.GreaterThan(api.Version) { 79 return errors.ErrorCodeNewerClientVersion.WithArgs(apiVersion, api.Version) 80 } 81 if apiVersion.LessThan(api.MinVersion) { 82 return errors.ErrorCodeOldClientVersion.WithArgs(apiVersion, api.Version) 83 } 84 85 w.Header().Set("Server", "Docker/"+dockerversion.VERSION+" ("+runtime.GOOS+")") 86 ctx = context.WithValue(ctx, httputils.APIVersionKey, apiVersion) 87 return handler(ctx, w, r, vars) 88 } 89 } 90 91 // handleWithGlobalMiddlwares wraps the handler function for a request with 92 // the server's global middlewares. The order of the middlewares is backwards, 93 // meaning that the first in the list will be evaludated last. 94 // 95 // Example: handleWithGlobalMiddlewares(s.getContainersName) 96 // 97 // s.loggingMiddleware( 98 // s.userAgentMiddleware( 99 // s.corsMiddleware( 100 // versionMiddleware(s.getContainersName) 101 // ) 102 // ) 103 // ) 104 // ) 105 func (s *Server) handleWithGlobalMiddlewares(handler httputils.APIFunc) httputils.APIFunc { 106 middlewares := []middleware{ 107 versionMiddleware, 108 s.corsMiddleware, 109 s.userAgentMiddleware, 110 s.loggingMiddleware, 111 } 112 113 h := handler 114 for _, m := range middlewares { 115 h = m(h) 116 } 117 return h 118 }