gorilla mux 和 negroni 教程:后台中间件怎么写
Go中的路径前缀中间件
最近,我在一个项目中工作,我发现自己想根据路线的前缀路径设置一些自定义中间件。我没有看到很多很好的资源来解释如何执行此操作,因此这是我的尝试。
不幸的是,我无法分享我的真实代码,但是我可以做的是假装我们正在构建一个应用程序和api,以帮助人们压缩事物。首先,让我们看一下我们希望应用程序具有的一些路线。
-/ blog
-这是我们写关于如何制作出色技术文章的地方。
-/价格
-/ dashboard / *
-仪表板前缀下将有几条路由,这是我们将使用某些中间件过滤掉未经身份验证的用户的地方。
-/ api / *
-最后我们有了我们的API路由。我们有一些高级用户,他们显然有很多需要压缩的文件,因此我们需要给他们一种发送API请求的方法。我们可能通过标头而不是cookie对这些用户进行身份验证。
现在我们已经掌握了路由路径的要点,再检查一下我们将使用到的一些库。
所需库
我们将使用以下库:
- negroni 用于我们的中间件
- gorilla mux 用于我们的路由
- http.ServeMux] 在中间件中封装特定的路径前缀
您可以很容易地把我们将使用到的技术应用到其他库中,但为了简单起见,我们将使用特定的包,这样我们就不局限于伪代码了。
编写路由
让我们从快速编写路由开始。
func main() {
r := mux.NewRouter().StrictSlash(false)
r.HandleFunc("/blog", blog)
r.HandleFunc("/pricing", pricing)
dash := r.PathPrefix("/dashboard").Subrouter()
dash.HandleFunc("/", dashboardIndex)
dash.HandleFunc("/things", dashboardThings)
dash.HandleFunc("/things/compress", dashboardCompressAllTheThings)
api := r.PathPrefix("/api").Subrouter()
api.HandleFunc("/things", apiThings)
api.HandleFunc("/things/compress", apiCompressAllTheThings)
http.ListenAndServe(":3000", r)
}
我们没有实现任何的 http.Handler
,但假设传入 HandleFunc
的所有函数都是 http.HandlerFunc 类型。
中间件
首先,让我们创建一个经典的 negroni
实例,并将其应用于我们所有的路由。这可以处理日志记录和紧急恢复等事务。
func main() {
// ... this is all roughly the same code from our
// last example
n := negroni.Classic()
n.UseHandler(r)
http.ListenAndServe(":3000", n)
}
最后三行是主函数中唯一更改和新增的行。 我们创建了一个 negroni.Negroni
的实例。 negroni.Negroni
采用 negroni.Classic
,然后告知 negroni.Classic
使用我们的 mux.Router
作为处理器。最后用我们的 negroni
处理器启动服务监听 3000 端口。
在我们继续前进之前,我们需要为我们的其他路由编写一些中间件。请记住,我们需要验证用户是否登录了我们每个不同类型的终端。
func DashboardMiddleware(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
// 验证客户是否以有效 cookie 登录 w/
validCookie := true
if validCookie {
next(w, r)
} else {
// 重定向至登录页
http.Redirect(w, r, "/login", http.StatusFound)
}
}
func APIMiddleware(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
// 验证客户是否以有效 cookie 登录 w/
validHeader := true
if validHeader {
next(w, r)
} else {
// 重定向至登录页
http.Redirect(w, r, "/login", http.StatusFound)
}
}
好吧,很明显,我不打算把所有的代码都写出来,但让我们假装我们写了。
基于路由前缀指定中间件
这是魔法发生的地方,也是事情变得令人困惑的地方。
我发现为路径前缀指定中间件的最简单方法是设置第二个 muxer
(以下使用 sirMuxalot
变量),其中包含我们希望应用中间件的路径前缀,然后将起初封装在一些中间件中的路由传递给这些路由。
这能起作用是因为我们定义的路径前缀与传入的网络请求的路径匹配时,sirMuxalot
路由才会调用封装有中间件的路由。
sirMuxalot := http.NewServeMux()
sirMuxalot.Handle("/", r)
sirMuxalot.Handle("/api/", negroni.New(
negroni.HandlerFunc(APIMiddleware),
negroni.Wrap(r),
))
sirMuxalot.Handle("/dashboard/", negroni.New(
negroni.HandlerFunc(DashboardMiddleware),
negroni.Wrap(r),
))
n := negroni.Classic()
n.UseHandler(sirMuxalot)
http.ListenAndServe(":3000", n)
将我们的路由封装在多个不同的中间件中看似奇怪,但效果非常好,是解决这个问题的更优雅的方案之一。
就这样吧。如果代码看起来仍然有点模糊,我建议多操练操练。同样,您不必非得使用 negroni
或任何其他特定的中间件来工作,所以请随时使用自定义代码或不同的库。
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
推荐文章: