httprouter文档
13 分钟阅读
HttpRouter
HttpRouter 是一个轻量级高性能的 Go 语言 HTTP 请求路由器(也称为多路复用器multiplexer或简称 mux)。
与 Go 标准库中的 net/http
包中的默认 mux 不同,该路由器支持路由模式中的变量,并匹配请求方法。它也具有更好的可扩展性。
该路由器针对高性能和小内存占用进行了优化。即使在非常长的路径和大量路由的情况下,它也能良好地扩展。使用压缩动态 trie(基数树 radix tree)结构进行高效匹配。
特性
只有显式匹配:在其他路由器(如 http.ServeMux)中,请求的 URL 路径可以匹配多个模式。因此它们有一些尴尬的模式优先级规则,比如最长匹配或首先注册,首先匹配。通过这个路由器的设计,一个请求只能精确地匹配一个或零个路由。结果,也没有意外的匹配,这使得它非常适合 SEO 并改善了用户体验。
不再关心尾部斜杠:选择您喜欢的URL样式,如果缺少尾部斜杠或多了一个,路由器会自动重定向客户端。当然,只有当新路径有处理程序时,它才会这样做。如果您不喜欢,可以关闭此行为。
路径自动纠正:除了在不增加额外成本的情况下检测缺少或附加的尾随斜杠外,路由器还可以修复错误的大小写和删除多余的路径元素(如 ../
或 //
)。你的用户中有 CAPTAIN CAPS LOCK 吗?HttpRouter 可以通过进行大小写不敏感的查找并将其重定向到正确的 URL 来帮助他。
在路由模式中使用参数:停止解析请求的 URL 路径,只需给路径段一个名称,路由器就会将动态值传递给您。由于路由器的设计,路径参数非常便宜。
零垃圾:匹配和调度过程不会产生任何垃圾。仅进行堆分配以构建路径参数的键值对切片和构建新的上下文和请求对象(仅在标准的 Handler/HandlerFunc
API 中)。在三参数 API 中,如果请求路径不包含参数,则不需要进行任何堆分配。
最佳性能:基准测试说明一切。有关实现的技术细节,请参见下面。
不再有服务器崩溃的问题:您可以设置一个Panic处理程序来处理在处理HTTP请求时发生的panic。路由器会恢复并让PanicHandler
记录发生的情况并提供一个漂亮的错误页面。
完美适用于API:该路由器设计鼓励构建合理的分层RESTful API。此外,它还具有内置的OPTIONS请求和405 Method Not Allowed
响应的本机支持。
当然,您也可以设置自定义的NotFound和MethodNotAllowed处理程序并提供静态文件。
用法
这只是一个简单的介绍,请查看文档以获取详细信息。
让我们从一个微不足道的例子开始:
|
|
命名参数
正如您所看到的,:name
是一个命名参数。值可以通过httprouter.Params
访问,它只是httprouter.Params
的切片。您可以通过在切片中使用其索引或使用ByName(name)
方法来获取参数的值::name
可以通过ByName("name")
检索。
当使用http.Handler
(使用router.Handler
或http.HandlerFunc
)而不是使用第三个函数参数的HttpRouter的处理API时,命名参数存储在request.Context
中。在下面的"为什么它不能与http.Handler
一起工作?“下面查看更多信息。
命名参数仅匹配单个路径段:
Pattern: /user/:user
/user/gordon match
/user/you match
/user/gordon/profile no match
/user/ no match
注意:由于此路由器仅具有显式匹配,因此您无法在相同的路径段上同时为相同的请求方法注册静态路由和参数。例如,您不能同时为/user/new
和/user/:user
注册模式,以进行相同的请求方法。不同请求方法的路由与彼此独立。
捕获所有参数
第二种类型是捕获所有参数,格式为*name
。正如名称所示,它们匹配所有内容。因此,它们必须始终位于模式的末尾:
Pattern: /src/*filepath
/src/ match
/src/somefile.go match
/src/subdir/somefile.go match
它是如何工作的?
路由器依赖于树形结构,该结构大量使用公共前缀,基本上是一棵紧凑的前缀树(或者称作Radix树)。具有公共前缀的节点也共享一个共同的父节点。以下是GET
请求方法的路由树的简短示例:
Priority Path Handle
9 \ *<1>
3 ├s nil
2 |├earch\ *<2>
1 |└upport\ *<3>
2 ├blog\ *<4>
1 | └:post nil
1 | └\ *<5>
2 ├about-us\ *<6>
1 | └team\ *<7>
1 └contact\ *<8>
每个 *<num>
表示一个处理程序函数(指针)的内存地址。如果您从根节点到叶子节点沿着树的路径走,您将获得完整的路由路径,例如 \blog:post\
,其中 :post
只是一个占位符(参数),用于实际的帖子名称。与哈希映射不同,树形结构也允许我们使用 :post
参数等动态部分,因为我们实际上是针对路由模式进行匹配,而不仅仅是比较哈希值。正如基准测试所显示的那样,这非常有效和高效。
由于 URL 路径具有层次结构并且只使用有限的字符集(字节值),很可能存在许多公共前缀。这使我们可以轻松地将路由缩小为越来越小的问题。此外,路由器为每个请求方法管理一个单独的树。一方面,它比在每个单独节点中保存方法->处理程序映射更节省空间,另一方面它还允许我们在甚至开始查找前缀树之前大大减少路由问题。
为了更好的可扩展性,每个树级别上的子节点按优先级排序,其中优先级仅为在子节点(孩子、孙子等)中注册的处理程序数量。这种方法有两个帮助:
- 首先,先评估最多的路由路径节点,这有助于使尽可能多的路由尽快到达。
- 这是某种成本补偿。最长可达路径(最高成本)总是可以首先进行评估。下面的图表显示了树形结构。节点从上到下,从左到右进行评估。
├------------
├---------
├-----
├----
├--
├--
└-
为什么它不能与http.Handler
一起工作?
它可以!路由器本身实现了http.Handler
接口。此外,路由器提供了方便的适配器,使得当注册路由时,可以将它们用作httprouter.Handle来使用http.Handlers和http.HandlerFuncs。
命名参数可以通过request.Context
访问:
|
|
或者,也可以使用params := r.Context().Value(httprouter.ParamsKey)
而不是使用helper函数。
尝试自己使用它,使用HttpRouter非常简单。这个包是紧凑而简约的,但也可能是最容易设置的路由器之一。
自动OPTIONS响应和CORS
有人可能希望修改自动响应OPTIONS请求的方式,例如支持CORS预检请求或设置其他标头。可以使用Router.GlobalOPTIONS处理程序来实现:
|
|
我在哪里可以找到中间件X?
此包只提供一个非常高效的请求路由器和一些额外的功能。该路由器只是一个http.Handler,您可以在路由器之前链接任何http.Handler兼容的中间件,例如Gorilla处理程序。或者你可以自己编写,这非常容易!
或者,您可以尝试基于HttpRouter的Web框架。
多域/子域
以下是一个快速的例子:您的服务器是否提供多个域名/主机?您想使用子域吗?为每个主机定义一个路由器!
|
|
基本身份验证
另一个快速的例子:处理基本身份验证(RFC 2617):
|
|
使用NotFound处理程序进行链接
注意:可能需要将Router.HandleMethodNotAllowed设置为false
以避免出现问题。
您可以使用另一个http.Handler(例如另一个路由器)来处理无法由此路由器匹配的请求,方法是使用Router.NotFound处理程序进行链接。这样可以进行链接。
静态文件
NotFound
处理程序可以例如用于从根路径/
(如index.html
文件以及其他资源)提供静态文件:
// Serve static files from the ./public directory
// 从./public目录提供静态文件
router.NotFound = http.FileServer(http.Dir("public"))
但是,此方法规避了此路由器的严格核心规则以避免路由问题。更干净的方法是使用一个不同的子路径来提供文件,例如/static/*filepath
或/files/*filepath
。
基于HttpRouter的Web框架
如果HttpRouter对您来说有点过于简单,您可以尝试以下更高级的第三方Web框架,这些框架是基于HttpRouter包构建的:
- Ace:极速的 Go Web 框架
- api2go:用于 Go 的 JSON API 实现
- Gin:具有类似 Martini 的 API 和更好的性能
- Goat:Go 中极简的 REST API 服务器
- goMiddlewareChain:类似于 Express.js 的中间件链
- Hikaru:支持独立和 Google AppEngine
- Hitch:将 httprouter、httpcontext和中间件捆绑在一起
- httpway:支持具有上下文的中间件扩展的 httprouter 和具有优雅关闭支持的服务器
- kami:使用 x/net/context 的微型 Web 框架
- Medeina:受 Ruby 的 Roda 和 Cuba 启发
- Neko:用于 Golang 的轻量级 Web 应用框架
- pbgo:基于 Protobuf 的 mini RPC/REST 框架
- River:River 是一个简单轻量级的 REST 服务器
- siesta:具有上下文的可组合 HTTP 处理程序
- xmux:xmux 是 httprouter 在 xhandler(net/context 意识)之上的 fork
Documentation
Overview
Package httprouter is a trie based high performance HTTP request router.
A trivial example is:
|
|
The router matches incoming requests by the request method and the path. If a handle is registered for this path and method, the router delegates the request to that function. For the methods GET, POST, PUT, PATCH and DELETE shortcut functions exist to register handles, for all other methods router.Handle can be used.
The registered path, against which the router matches incoming requests, can contain two types of parameters:
Syntax Type
:name named parameter
*name catch-all parameter
Named parameters are dynamic path segments. They match anything until the next ‘/’ or the path end:
Path: /blog/:category/:post
Requests:
/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
Catch-all parameters match anything until the path end, including the directory index (the ‘/’ before the catch-all). Since they match anything until the end, catch-all parameters must always be the final path element.
Path: /files/*filepath
Requests:
/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
The value of parameters is saved as a slice of the Param struct, consisting each of a key and a value. The slice is passed to the Handle func as a third parameter. There are two ways to retrieve the value of a parameter:
// by the name of the parameter
user := ps.ByName("user") // defined by :user or *user
// by the index of the parameter. This way you can also get the name (key)
thirdKey := ps[2].Key // the name of the 3rd parameter
thirdValue := ps[2].Value // the value of the 3rd parameter
Index
- Variables
- func CleanPath(p string) string
- type Handle
- type Param
- type Params
- type 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)
Constants
This section is empty.
Variables
var ParamsKey = paramsKey{}
ParamsKey is the request context key under which URL params are stored.
Functions
func CleanPath
|
|
CleanPath is the URL version of path.Clean, it returns a canonical URL path for p, eliminating . and .. elements.
The following rules are applied iteratively until no further processing can be done:
- Replace multiple slashes with a single slash.
- Eliminate each . path name element (the current directory).
- Eliminate each inner .. path name element (the parent directory) along with the non-.. element that precedes it.
- Eliminate .. elements that begin a rooted path: that is, replace “/..” by “/” at the beginning of a path.
If the result of this process is an empty string, “/” is returned
Types
type Handle
|
|
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).
type Param <- 1.1.0
|
|
Param is a single URL parameter, consisting of a key and a value.
type Params <- 1.1.0
|
|
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 ParamsFromContext <- 1.2.0
|
|
ParamsFromContext pulls the URL parameters from a request context, or returns nil if none are present.
func (Params) ByName <- 1.1.0
|
|
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.
type Router
|
|
Router is a http.Handler which can be used to dispatch requests to different handler functions via configurable routes
func New
|
|
New returns a new initialized Router. Path auto-correction, including trailing slashes, is enabled by default.
(*Router) DELETE
|
|
DELETE is a shortcut for router.Handle(http.MethodDelete, path, handle)
(*Router) GET
|
|
GET is a shortcut for router.Handle(http.MethodGet, path, handle)
(*Router) HEAD <- 1.1.0
|
|
HEAD is a shortcut for router.Handle(http.MethodHead, path, handle)
(*Router) Handle
|
|
Handle registers a new request handle with the given path and method.
For GET, POST, PUT, PATCH and DELETE requests the respective shortcut functions can be used.
This function is intended for bulk loading and to allow the usage of less frequently used, non-standardized or custom methods (e.g. for internal communication with a proxy).
(*Router) Handler <- 1.1.0
|
|
Handler is an adapter which allows the usage of an http.Handler as a request handle. The Params are available in the request context under ParamsKey.
(*Router) HandlerFunc
|
|
HandlerFunc is an adapter which allows the usage of an http.HandlerFunc as a request handle.
(*Router) Lookup <- 1.1.0
|
|
Lookup allows the manual lookup of a method + path combo. This is e.g. useful to build a framework around this router. If the path was found, it returns the handle function and the path parameter values. Otherwise the third return value indicates whether a redirection to the same path with an extra / without the trailing slash should be performed.
(*Router) OPTIONS <- 1.1.0
|
|
OPTIONS is a shortcut for router.Handle(http.MethodOptions, path, handle)
(*Router) PATCH
|
|
PATCH is a shortcut for router.Handle(http.MethodPatch, path, handle)
(*Router) POST
|
|
POST is a shortcut for router.Handle(http.MethodPost, path, handle)
(*Router) PUT
|
|
PUT is a shortcut for router.Handle(http.MethodPut, path, handle)
(*Router) ServeFiles
|
|
ServeFiles serves files from the given file system root. The path must end with “/*filepath”, files are then served from the local path /defined/root/dir/*filepath. For example if root is “/etc” and *filepath is “passwd”, the local file “/etc/passwd” would be served. Internally a http.FileServer is used, therefore http.NotFound is used instead of the Router’s NotFound handler. To use the operating system’s file system implementation, use http.Dir:
router.ServeFiles("/src/*filepath", http.Dir("/var/www"))
(*Router) ServeHTTP
|
|
ServeHTTP makes the router implement the http.Handler interface.