Golang-httprouter 逃离我推掉我的手 2023-10-10 22:18 7阅读 0赞 ### 什么是httprouter ### httprouter谈不上是一个框架,它的性能非常优秀。完全可以用来代替默认的 ServeMux。 所以比较适合对性能要求高,路由相对简单扁平的业务,或者作为高层HTTP框架的内部模块。 httproute内部通过实现一个trie树来提高性能。 核心代码就是golang标准库中 http.Handler 接口,在该函数中实现自己的请求路由分发策略。 gorilla/mux也是一个第三方的路由器,但是性能一般 ### 为什么用httprouter ### ###### 说说net/http的不足: ###### * 不能单独的对请求方法(POST,GET等)注册特定的处理函数 * 不支持路由变量参数 * 不能自动对Path进行校准 * 性能一般、扩展性不足 ###### httprouter带来哪些便利? ###### * 仅支持精确匹配,及只匹配一个模式或不会匹配到任何模式。相对于其他一些mux,例如go原生的 http.ServerMux, 会使得一个请求URL匹配多个模式,从而需要有优先级顺序,例如最长匹配、最先匹配等等。 * 不需要关心URL结尾的斜杠 * 路径自动归一化和矫正 * 零内存分配、高性能 ### httprouter路由匹配 ### // /api,可以访问到 // /api/,不可以 http.HandleFunc("/api",func(w http.ResponseWriter,r *http.Request){ fmt.Println("/api") }) // /api,可以 // /api/,也可以 http.HandleFunc("/api/",func(w http.ResponseWriter,r *http.Request){ fmt.Println("/api") }) **httprouter的路径匹配规则** 两个路由命名捕获方式:(路由命名的捕获,不是路由参数的捕获) * :name named parameter (只能根据路由命名进行捕获) * \*name catch-all parameter (\*表示捕获任意内容) 其中:name的捕获方式是匹配内容直到下一个斜线或者路径的结尾。例如要为如下路径注册 handler: > Pattern: /user/:user > /user/gordon match > /user/you match > /user/gordon/profile no match > /user/ no match \*name的捕获方式是从指定位置开始 (包含前缀 “/”) 匹配到结尾: > Pattern: /src/`*filepath` > /src/ match > /src/somefile.go match > /src/subdir/somefile.go match > /src no match ### ### ### 简单案例 ### package main import ( "fmt" "net/http" "log" "github.com/julienschmidt/httprouter" ) func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { fmt.Fprint(w, "Welcome!\n") } func Hello(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { fmt.Fprintf(w, "hello, %s!\n", ps.ByName("name")) } func main() { router := httprouter.New() router.GET("/", Index) router.GET("/hello/:name", Hello) log.Fatal(http.ListenAndServe(":8080", router)) } ### 自动选项响应和CORS ### 有人可能希望修改对OPTIONS请求的自动响应,例如支持[CORS][]预飞行请求或设置其他标头。这可以通过[Router来实现GlobalOPTIONS][Router_GlobalOPTIONS]处理程序 router.GlobalOPTIONS = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Header.Get("Access-Control-Request-Method") != "" { // Set CORS headers header := w.Header() header.Set("Access-Control-Allow-Methods", header.Get("Allow")) header.Set("Access-Control-Allow-Origin", "*") } // Adjust status code to 204 w.WriteHeader(http.StatusNoContent) }) ### 多主机路由 ### 一台服务器ip, 绑定了多个域名a.example.com ,b.example.com ,那么针对不同的域名我们可以做不同的处理 //我们需要一个对象来实现http。处理程序接口。 //因此我们需要一个类型来实现ServeHTTP方法。 //我们在这里只使用映射,将主机名(带端口)映射到http。处理程序 type HostSwitch map[string]http.Handler // 在我们的新类型上实现ServeHTTP方法 func (hs HostSwitch) ServeHTTP(w http.ResponseWriter, r *http.Request) { //检查是否存在http。为给定主机注册处理程序。 //如果是,使用它来处理请求。 if handler := hs[r.Host]; handler != nil { handler.ServeHTTP(w, r) } else { // Handle host names for which no handler is registered http.Error(w, "Forbidden", 403) // Or Redirect? } } func main() { // 像往常一样初始化路由器 router := httprouter.New() router.GET("/", Index) router.GET("/hello/:name", Hello) // 创建一个新的HostSwitch并插入路由器(我们的http处理程序) // 例如example.com和端口12345 hs := make(HostSwitch) hs["example.com:12345"] = router // 使用HostSwitch在12345端口上监听和服务 log.Fatal(http.ListenAndServe(":12345", hs)) } ### Basic权限认证 ### 快速示例:处理的基本身份验证 账户密码是以`:`分割 `username:password` 然后转换为basic64 在请求头里添加 `Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ` package main import ( "fmt" "log" "net/http" "github.com/julienschmidt/httprouter" ) func BasicAuth(h httprouter.Handle, requiredUser, requiredPassword string) httprouter.Handle { return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { // 获取基本身份验证凭据 user, password, hasAuth := r.BasicAuth() if hasAuth && user == requiredUser && password == requiredPassword { // Delegate request to the given handle h(w, r, ps) } else { // Request Basic Authentication otherwise w.Header().Set("WWW-Authenticate", "Basic realm=Restricted") http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized) } } } func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { fmt.Fprint(w, "Not protected!\n") } func Protected(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { fmt.Fprint(w, "Protected!\n") } func main() { user := "gordon" pass := "secret!" router := httprouter.New() router.GET("/", Index) router.GET("/protected/", BasicAuth(Protected, user, pass)) log.Fatal(http.ListenAndServe(":8080", router)) } ![在这里插入图片描述][241d60d901ab468c8532f2a2d4413093.gif] 点赞 -收藏-关注-便于以后复习和收到最新内容有其他问题在评论区讨论-或者私信我-收到会在第一时间回复在本博客学习的技术不得以任何方式直接或者间接的从事违反中华人民共和国法律,内容仅供学习、交流与参考 免责声明:本文部分素材来源于网络,版权归原创者所有,如存在文章/图片/音视频等使用不当的情况,请随时私信联系我、以迅速采取适当措施,避免给双方造成不必要的经济损失。感谢,配合,希望我的努力对你有帮助^\_^ [CORS]: https://developer.mozilla.org/en-US/docs/Glossary/preflight_request [Router_GlobalOPTIONS]: https://godoc.org/github.com/julienschmidt/httprouter#Router.GlobalOPTIONS [241d60d901ab468c8532f2a2d4413093.gif]: https://img-blog.csdnimg.cn/241d60d901ab468c8532f2a2d4413093.gif
还没有评论,来说两句吧...