The application framework should be known to have a routing module that looks at how Docker's HTTP requests are routed.
In Docker's Server.go file, the first entry is new.
The Func New (cfg *config) *server {//needs to create an instance of the server because the specific execution of the command is a function of the server object SRV: = &server{cfg:cfg,start:make (c Han struct{}),}//here is the operation to create the router r: = Createrouter (SRV) Srv.router = Rreturn SRV}
Let's take a look at the specifics of Createrouter.
Func createrouter (S *server) *mux. Router {r := mux. Newrouter () //router relies on the third package, address: Github.com/gorilla/muxif os. Getenv ("DEBUG") != " { profilersetup" (r, "/debug/")}//MAP->MAP[STRING]HTTPAPIFUNCM := map[string]map[string]httpapifunc{"HEAD": { //key,value->server corresponding processing function "/ Containers/{name:.*}/archive ": s.headcontainersarchive,}," GET ": {"/_ping ": s.ping, "/events": s.getevents, "/info": s.getinfo, "/version":     &NBsp; s.getversion, "/images/json": s.getimagesjson, "/images/search": s.getimagessearch, "/ Images/get ": s.getimagesget, "/images/{name:.*}/get": s.getimagesget, "/images/{name:.*}/history": s.getimageshistory, "/images/{name:.*}/json": S.getimagesbyname, "/containers/ps": S.getcontainersjson, "/containers/json": s.getcontainersjson, "/containers/{name:.*}/export": S.getcontainersexport, "/containers/{name:.*}/changes": s.getcontainerschanges, "/containers/{ Name:.*}/json ": s.getcontainersbyname,"/containers/{name:.*}/top ": s.getcontainerstop, "/containers/{name:.*}/logs": s.getcontainerslogs, "/containers/{name:.*}/stats": S.getcontainersstats, "/containers/{name:.*}/attach/ws": s.wscontainersattach, "/exec/{id:.*}/json": s.getexecbyid, "/containers/{name :. *}/archive ": s.getcontainersarchive,"/volumes ": &nbsP; s.getvolumeslist, "/volumes/{name:.*}": s.getvolumebyname,}, "POST": {"/ Auth ": s.postauth, "/commit": S.postcommit, "/build": s.postbuild, "/images/create": s.postimagescreate, "/images/load ": S.postimagesload, "/images/{name:.*}/puSH ": s.postimagespush,"/images/{name:.*}/tag ": s.postimagestag, "/containers/create": s.postcontainerscreate, "/containers/{name:.*}/kill": s.postcontainerskill, "/containers/{name:.*}/pause": s.postcontainerspause, "/ Containers/{name:.*}/unpause ": s.postcontainersunpause,"/containers/{name:.*}/restart ": S.postcontainersrestart, "/containers/{name:.*}/start": s.postcontainersstart, "/containers/{ Name:.*}/stop ": s.postcontainersstop,"/containers/{name:.*}/wait ": s.postcontainerswait, "/containers/{name:.*}/resize": s.postcontainersresize, "/containers/{ Name:.*}/attach ": s.postcontainersattach,"/containers/{name:.*}/copy ": S.postcontainerscopy, "/containers/{name:.*}/exec": s.postcontainerexeccreate, "/exec/{name:.*}/start": s.postcontainerexecstart, "/exec/{name:.*}/resize": s.postcontainerexecresize, "/containers/{name:.*}/rename": s.postcontainerrename, "/volumes": s.postvolumescreate,}, "PUT": {"/containers/{name:.*}/archive": S.putcontainersarchive,}, "DELETE": {"/containers/{name:.*}": s.deletecontainers, "/images/{name:.*}": s.deleteimages, "/volumes/{name:.*}": s.deletevolumes,}, " OPTIONS ": {" ": s.optionshandler,},}// if " Api-cors-header " is not given, but "Api-enable-cors" is true, we set cors to "*"// Otherwise, all head valUes will be passed to http handlercorsheaders := s.cfg.corsheadersif corsHeaders == "" && s.cfg.EnableCors {corsHeaders = "*"}for method, routes := range m {for route, fct := range Routes {logrus. DEBUGF ("registering %s, %s", method, route) localroute := route //For example _ pinglocalfct := fct //such as server.ping functions localmethod := method //such as "GET"// Build the handler function//golang's Httphandlerf := makehttphandler (s.cfg.Logging, localmethod, localroute, localfct, corsheaders, version. Version (s.cfg.version))// here is the creation of the route if localroute == "" {r.methods (Localmethod). Handlerfunc (f)} else {r.path ("/v{version:[0-9.") +} " + localroute). Methods (Localmethod). Handlerfunc (f) r.path (Localroute). Methods(Localmethod). Handlerfunc (f)}}}
Take a look at the example of the MUX:
They is defined using the format {name} or {Name:pattern}. If A regular expression pattern is not//defined, the matched variable would be anything until the next slashr: = Mux. Newrouter () R.handlefunc ("/products/{key}", Producthandler) R.handlefunc ("/articles/{category}/", Articlescategoryhandler) R.handlefunc ("/articles/{category}/{id:[0-9]+}", Articlehandler
The final MUX executes the Golang HTTP handler interface Servehttp
func (R *router) servehttp (w http. Responsewriter, req *http. Request) {// Clean path to canonical form and redirect.if p : = cleanpath (req. Url. Path); p != req. Url. path {// added 3 lines (philip schlump) - it was droping the query string and #whatever from query.// This matches with fix in go 1.2 r.c. 4 for same problem. go Issue:// http://code.google.com/p/go/issues/detail?id=5252url := *req. Urlurl.path = pp = url. String () W.header (). Set ("Location", p) W.writeheader (http. statusmovedpermanently) return}var match routematchvar handler http. Handlerif r.match (Req, &match) {handler = match. handler //here is the key step Setvars (Req, match. Vars) SetcurrentroUte (Req, match. Route)}if handler == nil {handler = r.notfoundhandlerif handler == nil {handler = http. Notfoundhandler ()}}if !r.keepcontext {defer context. Clear (req)}handler. Servehttp (w, req) //the anonymous function where the callback is finally executed}
Routing router of the Docker CLI