docker的cli的路由router

写过应用框架的都应该知道有个路由模块,来看看docker的http请求是怎么路由的

docker的server.go文件中,首先入口是New的时候

func New(cfg *Config) *Server {
        //需要创建Server的实例,因为命令的具体执行都是Server对象的函数  
	srv := &Server{
		cfg:   cfg,
		start: make(chan struct{}),
	}
	//这里就是创建Router的操作
	r := createRouter(srv)
	srv.router = r
	return srv
}

接下来看看createRouter的具体执行吧

func createRouter(s *Server) *mux.Router {
	r := mux.NewRouter() //Router依赖第三包,地址:github.com/gorilla/mux
	if os.Getenv("DEBUG") != "" { 
		profilerSetup(r, "/debug/")
	}
	//map->map[string]HTTPAPIFunc
	m := map[string]map[string]HTTPAPIFunc{
		"HEAD": {  //key,value->server对应的处理函数
			"/containers/{name:.*}/archive": s.headContainersArchive,
		},
		"GET": {
			"/_ping":                          s.ping,
			"/events":                         s.getEvents,
			"/info":                           s.getInfo,
			"/version":                        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":                        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 handler
	corsHeaders := s.cfg.CorsHeaders
	if corsHeaders == "" && s.cfg.EnableCors {
		corsHeaders = "*"
	}

	for method, routes := range m {
		for route, fct := range routes {
			logrus.Debugf("Registering %s, %s", method, route)
			 
			localRoute := route //例如_ping
			localFct := fct //例如Server.ping函数
			localMethod := method //例如"GET"

			// build the handler function

			//golang的HTTPHandler
			f := makeHTTPHandler(s.cfg.Logging, localMethod, localRoute, localFct, corsHeaders, version.Version(s.cfg.Version))

			// 这里就是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)
			}
		}
	}

再去看看mux的例子说明:

//They are defined using the format {name} or {name:pattern}. 
//If a regular expression pattern is not
// defined, the matched variable will be anything until the next slash

r := mux.NewRouter()
r.HandleFunc("/products/{key}", ProductHandler)
r.HandleFunc("/articles/{category}/", ArticlesCategoryHandler)
r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler

最终mux执行的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=5252
		url := *req.URL
		url.Path = p
		p = url.String()

		w.Header().Set("Location", p)
		w.WriteHeader(http.StatusMovedPermanently)
		return
	}
	var match RouteMatch
	var handler http.Handler
	if r.Match(req, &match) {
		handler = match.Handler //这里是关键步骤
		setVars(req, match.Vars)
		setCurrentRoute(req, match.Route)
	}
	if handler == nil {
		handler = r.NotFoundHandler
		if handler == nil {
			handler = http.NotFoundHandler()
		}
	}
	if !r.KeepContext {
		defer context.Clear(req)
	}
	handler.ServeHTTP(w, req) //这里最终执行回调的匿名函数
}
时间: 2025-01-07 02:37:18

docker的cli的路由router的相关文章

Android业务组件化之子模块SubModule的拆分以及它们之间的路由Router实现

前言: 前面分析了APP的现状以及业务组件化的一些探讨(Android业务组件化之现状分析与探讨),以及通信的桥梁Schema的使用(Android业务组件化之URL Schema使用),今天重点来聊下子模块SubModule的拆分以及它们之间的路由Router实现.本篇涉及的相关知识比较多,阅读本篇之间需要大致了解一下Java的注解(Java学习之注解Annotation实现原理).Java的动态代理机制(Java设计模式之代理模式(Proxy))等.业务组件化是一个循序渐进的过程,一开始很难

node_egg路由Router

路由(Router) 框架约定了app/router.js文件用于统一所有路由规则. Router 主要用来描述请求URL和具体承担执行动作的 Controller 的对应关系 定义路由(Router) // app/router.js 里面定义 URL 路由规则 module.exports = app => { const { router, controller } = app; router.get('/user/:id', controller.user.info); // 动态路由传

vue_路由Router

使用路由 Vue Router 是 Vue.js 官方的路由管理器.它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌 安装 vue项目创建时选择使用路由,项目将自动在根实例中注册 router 选项, 该 router 实例会注入到根组件下的所有子组件中,且子组件能通过 this.$router 访问到 假设vue项目创建没有选择使用路由,手动将路由注册到根实例中 $ npm install vue-router --save 手动创建目录 src/router/index.js

angular 路由router的用法总结

1,html页面 <!DOCTYPE html> <html lang="en" ng-app="myApp"> <head>     <meta charset="UTF-8">     <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, 

docker的cli是怎么解释参数的

接着上一篇docker命令attach源码分析,继续走 先看看prase的整体代码: //比如docker attach XXXID -> XXXID = arguments func (fs *FlagSet) Parse(arguments []string) error { fs.parsed = true  //打标志,作用:Parsed reports whether fs.Parse has been called,看看走到这一步没有 fs.args = arguments  for

docker的cli的call执行流程

平常我们输入一个命令,比如docker info,就是使用cli向daemon发送一次http请求,返回一些容器相关的参数 输入docker info的时候,如果daemon不是在后台运行,会有  INFO[0007] GET /v1.19/info 输出,GET相当于HTTP中的GET/POST中的method GET, v1.19相当于版本号,info就是命令的name咯 接下来我们分析源码: serverResp, err := cli.call("GET", "/co

6.1 路由router

路由将信息由源地址传递到目的地的一种角色. 一.路由简单应用举个例子: let express=require('express'); let app=express(); app.use(express.static('public')); // GET /home 显示 网站首页 app.get('/home',function(req,res){ res.setHeader('content-type','text/html;charset=utf-8'); res.end('网站首页')

vue路由-router

VueRouter基础 vue路由的注册 导入 <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script> # 可以是下载之后的 <script src="vue.min.js"></script> <script src="vue-router.js"></script> 定义一个匹配规则对

Vue的路由Router之导航钩子和元数据及匹配

一.文件结构 二.vue.js 打开此链接 https://cdn.bootcss.com/vue/2.6.10/vue.js 复制粘贴页面的所有内容 三.vue-router.js 打开此链接  https://cdn.bootcss.com/vue-router/3.0.6/vue-router.js 复制粘贴页面的所有内容 四.index.html 1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4