Docker Swarm程式碼分析筆記(8)——建立Docker API router

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。在上一篇提到的 API Server需要設定 HTTP處理函數:
......server.SetHandler(api.NewPrimary(cl, tlsConfig, &statusHandler{cl, nil, nil}, c.GlobalBool("debug"), c.Bool("cors")))......

api.Server結構體定義如下:

// Server is a Docker API server.type Server struct {    hosts  []string    tlsConfig  *tls.Config    dispatcher *dispatcher}

其中處理HTTP請求的相關方法如下:

// Dispatcher is a meta http.Handler. It acts as an http.Handler and forwards// requests to another http.Handler that can be changed at runtime.type dispatcher struct {    handler http.Handler}// SetHandler changes the underlying handler.func (d *dispatcher) SetHandler(handler http.Handler) {    d.handler = handler}// ServeHTTP forwards requests to the underlying handler.func (d *dispatcher) ServeHTTP(w http.ResponseWriter, r *http.Request) {    if d.handler == nil {        httpError(w, "No dispatcher defined", http.StatusInternalServerError)        return    }    d.handler.ServeHTTP(w, r)}// SetHandler is used to overwrite the HTTP handler for the API.// This can be the api router or a reverse proxy.func (s *Server) SetHandler(handler http.Handler) {    s.dispatcher.SetHandler(handler)}

Server.SetHandler所做的就是把handler賦給Server.dispatcher.handlerhandler類型是http.Handler:

type Handler interface {    ServeHTTP(ResponseWriter, *Request)}

api.NewPrimary利用了mux這個project

// NewPrimary creates a new API router.func NewPrimary(cluster cluster.Cluster, tlsConfig *tls.Config, status StatusHandler, debug, enableCors bool) *mux.Router {    // Register the API events handler in the cluster.    eventsHandler := newEventsHandler()    cluster.RegisterEventHandler(eventsHandler)    context := &context{        cluster:       cluster,        eventsHandler: eventsHandler,        statusHandler: status,        tlsConfig:     tlsConfig,    }    r := mux.NewRouter()    setupPrimaryRouter(r, context, enableCors)    if debug {        profilerSetup(r, "/debug/")    }    return r}

*mux.Router實現了ServeHTTP這個方法,所以符合http.Handler這個interface

// ServeHTTP dispatches the handler registered in the matched route.//// When there is a match, the route variables can be retrieved calling// mux.Vars(request).func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {    ......}

api.ServerListenAndServe()函數定義了新的http.Server變數,利用上面實現的api.Server.dispatcherServeHTTP方法來響應HTTP請求:

server = &http.Server{                Addr:    protoAddrParts[1],                Handler: s.dispatcher,            }

再看一下setupPrimaryRouter這個函數:

func setupPrimaryRouter(r *mux.Router, context *context, enableCors bool) {    for method, mappings := range routes {        for route, fct := range mappings {            log.WithFields(log.Fields{"method": method, "route": route}).Debug("Registering HTTP route")            localRoute := route            localFct := fct            wrap := func(w http.ResponseWriter, r *http.Request) {                log.WithFields(log.Fields{"method": r.Method, "uri": r.RequestURI}).Debug("HTTP request received")                if enableCors {                    writeCorsHeaders(w, r)                }                context.apiVersion = mux.Vars(r)["version"]                localFct(context, w, r)            }            localMethod := method            r.Path("/v{version:[0-9]+.[0-9]+}" + localRoute).Methods(localMethod).HandlerFunc(wrap)            r.Path(localRoute).Methods(localMethod).HandlerFunc(wrap)            if enableCors {                optionsMethod := "OPTIONS"                optionsFct := optionsHandler                wrap := func(w http.ResponseWriter, r *http.Request) {                    log.WithFields(log.Fields{"method": optionsMethod, "uri": r.RequestURI}).                        Debug("HTTP request received")                    if enableCors {                        writeCorsHeaders(w, r)                    }                    context.apiVersion = mux.Vars(r)["version"]                    optionsFct(context, w, r)                }                r.Path("/v{version:[0-9]+.[0-9]+}" + localRoute).                    Methods(optionsMethod).HandlerFunc(wrap)                r.Path(localRoute).Methods(optionsMethod).                    HandlerFunc(wrap)            }        }    }}

其中routes定義如下:

var routes = map[string]map[string]handler{    "HEAD": {        "/containers/{name:.*}/archive": proxyContainer,    },    "GET": {        "/_ping":                          ping,        "/events":                         getEvents,        "/info":                           getInfo,        ......        }    ......}

"HEAD": {        "/containers/{name:.*}/archive": proxyContainer,}

為例:
methodlocalMethod"HEAD"
mappings是:

{        "/containers/{name:.*}/archive": proxyContainer,}

routelocalRoute"/containers/{name:.*}/archive"
fctlocalFctproxyContainer
所以

r.Path("/v{version:[0-9]+.[0-9]+}" + localRoute).Methods(localMethod).HandlerFunc(wrap)r.Path(localRoute).Methods(localMethod).HandlerFunc(wrap)

就是為"/v*/containers/{name:.*}/archive""/containers/{name:.*}/archive"這個PATH"HEAD"操作註冊了wrap函數,而wrap函數則封裝了localFct,也就是proxyContainer函數。 另外,if enableCors部分與上述類似。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.