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