github.com/uppal0016/docker_new@v0.0.0-20240123060250-1c98be13ac2c/api/server/server.go (about) 1 package server 2 3 import ( 4 "crypto/tls" 5 "net" 6 "net/http" 7 "strings" 8 9 "github.com/Sirupsen/logrus" 10 "github.com/docker/docker/api/server/httputils" 11 "github.com/docker/docker/api/server/middleware" 12 "github.com/docker/docker/api/server/router" 13 "github.com/gorilla/mux" 14 "golang.org/x/net/context" 15 ) 16 17 // versionMatcher defines a variable matcher to be parsed by the router 18 // when a request is about to be served. 19 const versionMatcher = "/v{version:[0-9.]+}" 20 21 // Config provides the configuration for the API server 22 type Config struct { 23 Logging bool 24 EnableCors bool 25 CorsHeaders string 26 Version string 27 SocketGroup string 28 TLSConfig *tls.Config 29 } 30 31 // Server contains instance details for the server 32 type Server struct { 33 cfg *Config 34 servers []*HTTPServer 35 routers []router.Router 36 routerSwapper *routerSwapper 37 middlewares []middleware.Middleware 38 } 39 40 // New returns a new instance of the server based on the specified configuration. 41 // It allocates resources which will be needed for ServeAPI(ports, unix-sockets). 42 func New(cfg *Config) *Server { 43 return &Server{ 44 cfg: cfg, 45 } 46 } 47 48 // UseMiddleware appends a new middleware to the request chain. 49 // This needs to be called before the API routes are configured. 50 func (s *Server) UseMiddleware(m middleware.Middleware) { 51 s.middlewares = append(s.middlewares, m) 52 } 53 54 // Accept sets a listener the server accepts connections into. 55 func (s *Server) Accept(addr string, listeners ...net.Listener) { 56 for _, listener := range listeners { 57 httpServer := &HTTPServer{ 58 srv: &http.Server{ 59 Addr: addr, 60 }, 61 l: listener, 62 } 63 s.servers = append(s.servers, httpServer) 64 } 65 } 66 67 // Close closes servers and thus stop receiving requests 68 func (s *Server) Close() { 69 for _, srv := range s.servers { 70 if err := srv.Close(); err != nil { 71 logrus.Error(err) 72 } 73 } 74 } 75 76 // serveAPI loops through all initialized servers and spawns goroutine 77 // with Server method for each. It sets createMux() as Handler also. 78 func (s *Server) serveAPI() error { 79 var chErrors = make(chan error, len(s.servers)) 80 for _, srv := range s.servers { 81 srv.srv.Handler = s.routerSwapper 82 go func(srv *HTTPServer) { 83 var err error 84 logrus.Infof("API listen on %s", srv.l.Addr()) 85 if err = srv.Serve(); err != nil && strings.Contains(err.Error(), "use of closed network connection") { 86 err = nil 87 } 88 chErrors <- err 89 }(srv) 90 } 91 92 for i := 0; i < len(s.servers); i++ { 93 err := <-chErrors 94 if err != nil { 95 return err 96 } 97 } 98 99 return nil 100 } 101 102 // HTTPServer contains an instance of http server and the listener. 103 // srv *http.Server, contains configuration to create a http server and a mux router with all api end points. 104 // l net.Listener, is a TCP or Socket listener that dispatches incoming request to the router. 105 type HTTPServer struct { 106 srv *http.Server 107 l net.Listener 108 } 109 110 // Serve starts listening for inbound requests. 111 func (s *HTTPServer) Serve() error { 112 return s.srv.Serve(s.l) 113 } 114 115 // Close closes the HTTPServer from listening for the inbound requests. 116 func (s *HTTPServer) Close() error { 117 return s.l.Close() 118 } 119 120 func (s *Server) makeHTTPHandler(handler httputils.APIFunc) http.HandlerFunc { 121 return func(w http.ResponseWriter, r *http.Request) { 122 // Define the context that we'll pass around to share info 123 // like the docker-request-id. 124 // 125 // The 'context' will be used for global data that should 126 // apply to all requests. Data that is specific to the 127 // immediate function being called should still be passed 128 // as 'args' on the function call. 129 ctx := context.Background() 130 handlerFunc := s.handleWithGlobalMiddlewares(handler) 131 132 vars := mux.Vars(r) 133 if vars == nil { 134 vars = make(map[string]string) 135 } 136 137 if err := handlerFunc(ctx, w, r, vars); err != nil { 138 logrus.Errorf("Handler for %s %s returned error: %v", r.Method, r.URL.Path, err) 139 httputils.WriteError(w, err) 140 } 141 } 142 } 143 144 // InitRouter initializes the list of routers for the server. 145 // This method also enables the Go profiler if enableProfiler is true. 146 func (s *Server) InitRouter(enableProfiler bool, routers ...router.Router) { 147 for _, r := range routers { 148 s.routers = append(s.routers, r) 149 } 150 151 m := s.createMux() 152 if enableProfiler { 153 profilerSetup(m) 154 } 155 s.routerSwapper = &routerSwapper{ 156 router: m, 157 } 158 } 159 160 // createMux initializes the main router the server uses. 161 func (s *Server) createMux() *mux.Router { 162 m := mux.NewRouter() 163 164 logrus.Debugf("Registering routers") 165 for _, apiRouter := range s.routers { 166 for _, r := range apiRouter.Routes() { 167 f := s.makeHTTPHandler(r.Handler()) 168 169 logrus.Debugf("Registering %s, %s", r.Method(), r.Path()) 170 m.Path(versionMatcher + r.Path()).Methods(r.Method()).Handler(f) 171 m.Path(r.Path()).Methods(r.Method()).Handler(f) 172 } 173 } 174 175 return m 176 } 177 178 // Wait blocks the server goroutine until it exits. 179 // It sends an error message if there is any error during 180 // the API execution. 181 func (s *Server) Wait(waitChan chan error) { 182 if err := s.serveAPI(); err != nil { 183 logrus.Errorf("ServeAPI error: %v", err) 184 waitChan <- err 185 return 186 } 187 waitChan <- nil 188 } 189 190 // DisableProfiler reloads the server mux without adding the profiler routes. 191 func (s *Server) DisableProfiler() { 192 s.routerSwapper.Swap(s.createMux()) 193 } 194 195 // EnableProfiler reloads the server mux adding the profiler routes. 196 func (s *Server) EnableProfiler() { 197 m := s.createMux() 198 profilerSetup(m) 199 s.routerSwapper.Swap(m) 200 }