2

Go http.ServeMux中的模式匹配

 4 months ago
source link: https://colobu.com/2023/12/25/patterns-in-ServeMux-HandleFunc/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Go http.ServeMux中的模式匹配

Go 1.22中一个很大的变化是http.ServeMux中的模式匹配,先前这个功能是很多第三方的web框架或者router库实现的。

我们很有必要好好研究它,将来在实现HTTP API的时候可能优先使用它。

http.ServeMux是一个HTTP请求多路复用器,它将每个传入请求的URL与已注册的模式列表进行匹配,并调用与最接近URL匹配的模式对应的处理程序。

mux.HandleFunc("POST /items/create", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "POST item created")
mux.HandleFunc("/items/create", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "item created")
mux.HandleFunc("/items/{id}", func(w http.ResponseWriter, r *http.Request) {
id := r.PathValue("id")
fmt.Fprintf(w, "Item ID = %s", id)
mux.HandleFunc("/files/{path...}", func(w http.ResponseWriter, r *http.Request) {
path := r.PathValue("path")
fmt.Fprintf(w, "File path = %s", path)

和原来的HandleFunc相比,第一个参数貌似有了不一样的变化,除了正常的path之外,还有HTTP POST Method,还有{id}{path...}这样的变量,这就是Go 1.22中新增加的模式匹配。

通过PathValue可以获取路径中的通配符匹配的值。

模式匹配用在注册handler的时候,如下:

func Handle(pattern string, handler Handler)
func HandleFunc(pattern string, handler func(ResponseWriter, *Request))

其中pattern模式的格式是这样子的:[METHOD ][HOST]/[PATH], 中括号代表这一项可以省略。
因此POST /items/createPOST rpcx.io/items/createGET /items/123/items/123都是合法的模式。

如果不设置HTTP Method如POST,那么默认是匹配所有的HTTP Method。注意HTTP Method 之后有一个空格。
模式匹配GET会匹配GETHEAD,除此之外,其他的HTTP Method都是精确匹配。

如果未设置HOST,那么默认是匹配所有的HOST。否则,HOST必须完全匹配。

请求的路径中可以包含通配符,如"/b/{bucket}/o/{objectname...}"。配符名称必须是有效的Go标识符。通配符必须是完整的路径段,例如/b_{bucket}就不是一个合法的通配符。

  • /items/{id}: 正常情况下一个通配符只匹配一个路径段,比如匹配/items/123,但是不匹配/items/123/456
  • /items/{apth...}: 但是如果通配符后面跟着...,那么它就会匹配多个路径段,比如/items/123/items/123/456都会匹配这个模式。
  • /items/{$}: 以/结尾的模式会匹配所有以它为前缀的路径,比如/items//items/123/items/123/456都会匹配这个模式。如果以/{$}为后缀,那么表示严格匹配路径,不会匹配带后缀的路径,比如这个例子只会匹配/items/,不会匹配/items/123/items/123/456

在匹配过程中,模式路径和传入请求路径都会逐段解码。因此,例如,路径 /a%2Fb/100%25 被视为具有两个段,a/b100%。模式 /a%2fb/ 与之匹配,但模式 /a/b/ 则不匹配。

如果两个模式都可以匹配同一个路径咋办呢?比如/items/{id}/items/{path...}都可以匹配/items/123,那么谁优先呢?

  • 最具体的模式具有优先权。比如/items/{id}/items/更具体。
  • 如果两者都不更具体,则模式冲突。
    • 在冲突的情况下,具有主机的模式具有优先权 rpcx.io/items/{id}/items/{id}优先权更高。
    • 如果两者都没有HOST,则模式冲突,panic。 items/{id}/items/{index}都没有HOST,所以会panic。

后缀/的转发

/images/ 会导致ServeMux/images重定向到/images/除非你注册了/images的handler。

ServeMux 还负责清理URL请求路径和Host标头,去除端口号,并将包含 ... 段或重复斜杠的任何请求重定向到等效、更清晰的URL。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK