Journey源码分析四:url路由

在入口函数main()default分支中,对路由进行了注册,现在分析下。

##main()中路由注册相关代码

源码:

httpRouter := httptreemux.New()
// Blog and pages as http
server.InitializeBlog(httpRouter)
server.InitializePages(httpRouter)
// Admin as http
server.InitializeAdmin(httpRouter)
// Start http server
log.Println("Starting server without HTTPS support. Please enable HTTPS in " + filenames.ConfigFilename + " to improve security.")
log.Println("Starting http server on port " + httpPort + "...")
err := http.ListenAndServe(httpPort, httpRouter)
if err != nil {
	log.Fatal("Error: Couldn't start the HTTP server:", err)
}

###httptreemux.New()

func New() *TreeMux {
	root := &node{path: "/"}
	return &TreeMux{root: root,
		NotFoundHandler:         http.NotFound,
		MethodNotAllowedHandler: MethodNotAllowedHandler,
		HeadCanUseGet:           true,
		RedirectTrailingSlash:   true,
		RedirectCleanPath:       true,
		RedirectBehavior:        Redirect301,
		RedirectMethodBehavior:  make(map[string]RedirectBehavior),
		PathSource:              RequestURI,
	}
}

可以看到他返回了一个实例化的结构体TreeMux,这个结构体注册了根路径/,此外还包含一些默认的handle,如http.NotFound:

// NotFound replies to the request with an HTTP 404 not found error.
func NotFound(w ResponseWriter, r *Request) { Error(w, "404 page not found", StatusNotFound) }

###server.InitializeBlog(httpRouter)

func InitializeBlog(router *httptreemux.TreeMux) {
	// For index
	router.GET("/", indexHandler)
	router.GET("/:slug/", postHandler)
	router.GET("/page/:number/", indexHandler)
	// For author
	router.GET("/author/:slug/", authorHandler)
	router.GET("/author/:slug/:function/", authorHandler)
	router.GET("/author/:slug/:function/:number/", authorHandler)
	// For tag
	router.GET("/tag/:slug/", tagHandler)
	router.GET("/tag/:slug/:function/", tagHandler)
	router.GET("/tag/:slug/:function/:number/", tagHandler)
	// For serving asset files
	router.GET("/assets/*filepath", assetsHandler)
	router.GET("/images/*filepath", imagesHandler)
	router.GET("/content/images/*filepath", imagesHandler) // This is here to keep compatibility with Ghost
	router.GET("/public/*filepath", publicHandler)
}

这里使用了route.GET()函数注册路由,我们看下router.GET("/", indexHandler):

// Syntactic sugar for Handle("GET", path, handler)
func (t *TreeMux) GET(path string, handler HandlerFunc) {
	t.Handle("GET", path, handler)
}

t.Handle("GET", path, handler):

func (t *TreeMux) Handle(method, path string, handler HandlerFunc) {
	if path[0] != '/' {
		panic(fmt.Sprintf("Path %s must start with slash", path))
	}

	addSlash := false
	if len(path) > 1 && path[len(path)-1] == '/' && t.RedirectTrailingSlash {
		addSlash = true
		path = path[:len(path)-1]
	}
	
	//将path注册到root子节点中去,并返回子节点的引用
	node := t.root.addPath(path[1:], nil)
	if addSlash {
		node.addSlash = true
	}
	//最终注册路由
	node.setHandler(method, handler)
}

node.setHandler(method, handler):

func (n *node) setHandler(verb string, handler HandlerFunc) {
	if n.leafHandler == nil {
		n.leafHandler = make(map[string]HandlerFunc)
	}
	_, ok := n.leafHandler[verb]
	if ok {
		panic(fmt.Sprintf("%s already handles %s", n.path, verb))
	}
	n.leafHandler[verb] = handler
}

剩下的路由注册server.InitializeBlog(httpRouter),server.InitializePages(httpRouter),server.InitializeAdmin(httpRouter)都大同小异。

这里只是介绍了路由注册的整体流程,其中最复杂的地方是func (t *TreeMux) Handle(method, path string, handler HandlerFunc)中的node := t.root.addPath(path[1:], nil)函数,不过源码有详细的注释,有兴趣的自行研究。

转载于:https://my.oschina.net/fmnisme/blog/502715

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值