Go 1.22中一个很大的变化是http.ServeMux
中的模式匹配,先前这个功能是很多第三方的web框架或者router库实现的。
我们很有必要好好研究它,将来在实现HTTP API的时候可能优先使用它。
http.ServeMux
是一个HTTP请求多路复用器,它将每个传入请求的URL与已注册的模式列表进行匹配,并调用与最接近URL匹配的模式对应的处理程序。
比如:
|
|
和原来的HandleFunc
相比,第一个参数貌似有了不一样的变化,除了正常的path之外,还有HTTP POST Method,还有{id}
和{path...}
这样的变量,这就是Go 1.22中新增加的模式匹配。
通过PathValue
可以获取路径中的通配符匹配的值。
模式匹配
模式匹配用在注册handler的时候,如下:
|
|
其中pattern
模式的格式是这样子的:[METHOD ][HOST]/[PATH]
, 中括号代表这一项可以省略。
因此POST /items/create
、POST rpcx.io/items/create
、GET /items/123
、/items/123
都是合法的模式。
如果不设置HTTP Method如POST
,那么默认是匹配所有的HTTP Method。注意HTTP Method 之后有一个空格。
模式匹配GET
会匹配GET
和HEAD
,除此之外,其他的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/b
和 100%
。模式 /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。