網站首頁 編程語言 正文
HttpRouter是一個輕量級但卻非常高效的multiplexer。手冊:
https://godoc.org/github.com/julienschmidt/httprouter
https://github.com/julienschmidt/httprouter
用法示例
package main import ( "fmt" "github.com/julienschmidt/httprouter" "net/http" "log" ) 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)) }
首先執行:
go get github.com/julienschmidt/httprouter
然后再啟動web服務:
go run xxx.go
和http包的ServeMux用法其實很類似。上面定義了兩個httprouter中的handle,類似于http包中的http.HandlerFunc類型,具體的對應關系后文會解釋,只要認為它是handler,是處理對應請求的就行了。然后使用New()方法創建了實例,并使用GET()方法為兩個模式注冊了對應的handler。
需要注意的是,第二個模式"/hello/:name",它可以用來做命名匹配,類似于正則表達式的命名捕獲分組。后面會詳細解釋用法。
httprouter用法說明
Variables func CleanPath(p string) string type Handle type Param type Params func ParamsFromContext(ctx context.Context) Params func (ps Params) ByName(name string) string type Router func New() *Router func (r *Router) DELETE(path string, handle Handle) func (r *Router) GET(path string, handle Handle) func (r *Router) HEAD(path string, handle Handle) func (r *Router) Handle(method, path string, handle Handle) func (r *Router) Handler(method, path string, handler http.Handler) func (r *Router) HandlerFunc(method, path string, handler http.HandlerFunc) func (r *Router) Lookup(method, path string) (Handle, Params, bool) func (r *Router) OPTIONS(path string, handle Handle) func (r *Router) PATCH(path string, handle Handle) func (r *Router) POST(path string, handle Handle) func (r *Router) PUT(path string, handle Handle) func (r *Router) ServeFiles(path string, root http.FileSystem) func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request)
type Handle
httprouter中的Handle類似于http.HandlerFunc,只不過它支持第三個參數Params。
type Handle func(http.ResponseWriter, *http.Request, Params) Handle is a function that can be registered to a route to handle HTTP requests. Like http.HandlerFunc, but has a third parameter for the values of wildcards (variables).
例如前面示例中的Index()和Hello()都是Handle類型的實例。
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")) }
注冊handler
httprouter.Router類型類似于http包中的ServeMux,它實現了http.Handler接口,所以它是一個http.Handler。它可以將請求分配給注冊好的handler。
type Router struct {} func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request)
除此之外,Router提供了不少方法,用來指示如何為路徑注冊handler。
func (r *Router) Handle(method, path string, handle Handle) func (r *Router) Handler(method, path string, handler http.Handler) func (r *Router) HandlerFunc(method, path string, handler http.HandlerFunc)
httprouter.Handle()用于為路徑注冊指定的Handle,而httprouter.Handle對應于http.HandlerFunc,所以是直接將Handle類型的函數綁定到指定路徑上。同時,它還可以指定http方法:GET, POST, HEAD, PUT, PATCH, DELETE, OPTIONS。
這些方法還有對應的各自縮寫:
func (r *Router) DELETE(path string, handle Handle) func (r *Router) GET(path string, handle Handle) func (r *Router) HEAD(path string, handle Handle) func (r *Router) OPTIONS(path string, handle Handle) func (r *Router) PATCH(path string, handle Handle) func (r *Router) POST(path string, handle Handle) func (r *Router) PUT(path string, handle Handle)
例如,Get()等價于route.Handle("GET", path, handle)。
例如上面的示例中,為兩個路徑注冊了各自的httprouter.Handle函數。
router := httprouter.New() router.GET("/", Index) router.GET("/hello/:name", Hello)
Handler()方法是直接為指定http方法和路徑注冊http.Handler;HandlerFunc()方法則是直接為指定http方法和路徑注冊http.HandlerFunc。
Param相關
type Param struct { Key string Value string } Param is a single URL parameter, consisting of a key and a value. type Params []Param Params is a Param-slice, as returned by the router. The slice is ordered, the first URL parameter is also the first slice value. It is therefore safe to read values by the index. func (ps Params) ByName(name string) string ByName returns the value of the first Param which key matches the given name. If no matching Param is found, an empty string is returned.
Param類型是key/value型的結構,每個分組捕獲到的值都會保存為此類型。正如前面的示例中:
router.GET("/hello/:name", Hello)
這里的:name
就是key,當請求的URL路徑為/hello/abc
,則key對應的value為abc。也就是說保存了一個Param實例:
Param{ Key: "name", Value: "abc", }
更多的匹配用法稍后解釋。
Params是Param的slice。也就是說,每個分組捕獲到的key/value都存放在這個slice中。
ByName(str)方法可以根據Param的Key檢索已經保存在slice中的Param的Value。正如示例中:
func Hello(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { fmt.Fprintf(w, "hello, %s!\n", ps.ByName("name")) } router.GET("/hello/:name", Hello)
這里ByName("name")
將檢索保存在slice中,Key="name"的Param,且返回這個Param中的Value。
由于Params是slice結構,除了ByName()方法可以檢索key/value,通過slice的方法也可以直接檢索:
ps[0].Key ps[0].Value
路徑匹配規則
httprouter要為路徑注冊handler的適合,路徑可以進行命名捕獲。有兩種命名捕獲的方式:
Syntax Type :name named parameter *name catch-all parameter
其中:name
的捕獲方式是匹配內容直到下一個斜線或者路徑的結尾。例如要為如下路徑注冊handler:
Path: /blog/:category/:post
當請求路徑為:
/blog/go/request-routers match: category="go", post="request-routers" /blog/go/request-routers/ no match, but the router would redirect /blog/go/ no match /blog/go/request-routers/comments no match
*name
的捕獲方式是從指定位置開始(包含前綴"/")匹配到結尾:
Path: /files/*filepath /files/ match: filepath="/" /files/LICENSE match: filepath="/LICENSE" /files/templates/article.html match: filepath="/templates/article.html" /files no match, but the router would redirect
再解釋下什么時候會進行重定向。在Router類型中,第一個字段控制尾隨斜線的重定向操作:
type Router struct { RedirectTrailingSlash bool ... }
如果請求的URL路徑包含或者不包含尾隨斜線時,但在注冊的路徑上包含了或沒有包含"/"的目標上定義了handler,但是會進行301重定向。簡單地說,不管URL是否帶尾隨斜線,只要注冊路徑不存在,但在去掉尾隨斜線或加上尾隨斜線的路徑上定義了handler,就會自動重定向。
例如注冊路徑為/foo
,請求路徑為/foo/
,會重定向。
下面還有幾種會重定向的情況:
注冊路徑:/blog/:category/:post 請求URL路徑:/blog/go/request-routers/ 注冊路徑:/blog/:category 請求URL路徑:/blog/go 注冊路徑:/files/*filepath 請求URL路徑:/files
Lookup()
func (r *Router) Lookup(method, path string) (Handle, Params, bool)
Lookup根據method+path檢索對應的Handle,以及Params,并可以通過第三個返回值判斷是否會進行重定向。
原文鏈接:https://www.cnblogs.com/f-ck-need-u/p/10020917.html
相關推薦
- 2022-04-14 Mac快速解決zsh: command not found: conda的方法
- 2023-06-17 tensorflow1.x和tensorflow2.x中的tensor轉換為字符串的實現_pytho
- 2022-11-18 詳解Rust中三種循環(loop,while,for)的使用_Rust語言
- 2022-05-11 深入理解AQS之Semaphore&CountDownLatch&Cyclic詳解
- 2022-08-16 Hive常用日期格式轉換語法_數據庫其它
- 2022-07-02 Prometheus+Grafana監控Docker容器和Linux主機
- 2022-08-13 Android開發Viewbinding委托實例詳解_Android
- 2023-01-11 一文帶你解密Python迭代器的實現原理_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支