golang的urlrouter

起因

做权限管理,需要匹配路由,这个需要路由查找算法,一般采用tried 树,然而之前没研究过,一时半会也写不出来。在GitHub上找了一些router,然而都和http请求结合的很紧密,剥离一个纯粹的url匹配很困难。
后来发现了naoina/denco,作者就是采用分开设计的方式,于是直接拿来用了。

问题

经过测试却发现,denco对restful形式的路由支持很好,然而传统的问号后面接请求参数形式不支持,于是修改了一下router.go里的makeRecords函数,添加了如下代码:

//添加了?
if strings.Contains(r.Key,string(QueryCharacter)) {
        oldKey := r.Key
        r.Key += string(WildcardCharacter) + termChar
        params = append(params, &record{Record: r})

        r.Key = strings.Replace(oldKey,string(QueryCharacter),"",1)
        statics = append(statics, &record{Record: r})
        continue
}

当有规则里有问号匹配有问号和无问号的,当没有问号时完全匹配

测试代码

package main

import (

	"fmt"
	"github.com/dwdcth/urlrouter"
)
type route struct {
	name string
}

func main() {
	router := urlrouter.New()
	router.Build([]urlrouter.Record{
		{"/", &route{"root"}},
		{"/user/:id", &route{"user"}},
		{"/user/:name/:id", &route{"username"}},
		{"/static/*filepath", &route{"static"}},
		{"/test?", &route{"test"}},
	})

	data, params, found := router.Lookup("/")
	// print `&main.route{name:"root"}, denco.Params(nil), true`.
	fmt.Printf("%#v, %#v, %#v
", data, params, found)

	data, params, found = router.Lookup("/user/hoge")
	// print `&main.route{name:"user"}, denco.Params{denco.Param{Name:"id", Value:"hoge"}}, true`.
	fmt.Printf("%#v, %#v, %#v
", data, params, found)

	data, params, found = router.Lookup("/user/hoge/7")
	// print `&main.route{name:"username"}, denco.Params{denco.Param{Name:"name", Value:"hoge"}, denco.Param{Name:"id", Value:"7"}}, true`.
	fmt.Printf("%#v, %#v, %#v
", data, params, found)

	data, params, found = router.Lookup("/static/path/to/file")
	// print `&main.route{name:"static"}, denco.Params{denco.Param{Name:"filepath", Value:"path/to/file"}}, true`.
	fmt.Printf("%#v, %#v, %#v
", data, params, found)

	// both /test and /test?params can found
	data, params, found = router.Lookup("/test")
	// print `&main.route{name:"test"}, urlrouter.Params(nil), true`.
	fmt.Printf("%#v, %#v, %#v
", data, params, found)

	data, params, found = router.Lookup("/test?hello=world&name=tom")
	// print `&main.route{name:"test"}, urlrouter.Params{urlrouter.Param{Name:"", Value:"hello=world&name=tom"}}, true`.
	fmt.Printf("%#v, %#v, %#v
", data, params, found)

}

修改后的代码在此

原文地址:https://www.cnblogs.com/xdao/p/golang_urlrouter.html