当前位置:首页 > 科技  > 软件

提升Go的HTTP路由器的提案

来源: 责编: 时间:2023-08-14 22:01:10 428观看
导读译者 | 刘汪洋审校 | 重楼Go 的标准库中包含一个稳定且成熟的 HTTP 服务器。然而,内置的请求路由器http.ServeMux 功能较为简洁,因此你常常需要自己编写路由代码。其主要短板是,它并未支持 HTTP 方法的匹配(如GET和POST的

译者 | 刘汪洋asQ28资讯网——每日最新资讯28at.com

审校 | 重楼asQ28资讯网——每日最新资讯28at.com

Go 的标准库中包含一个稳定且成熟的 HTTP 服务器。然而,内置的请求路由器http.ServeMux 功能较为简洁,因此你常常需要自己编写路由代码。asQ28资讯网——每日最新资讯28at.com

asQ28资讯网——每日最新资讯28at.com

其主要短板是,它并未支持 HTTP 方法的匹配(如GET和POST的区别),同时也无法持/users/{user}/settings这种类型的通配符路径。然而,这两个功能几乎是所有 REST 风格的 API 服务器所必需的。asQ28资讯网——每日最新资讯28at.com

当然,你可以选择自行实现这些功能。在我以前的一篇文章 Go 中不同的 HTTP 路由方法中,提到过有一些优秀的第三方包可以实现更高级的路由功能,并且只需 约 30 行代码 就能够在不借助任何第三方库的情况下实现类似的功能。asQ28资讯网——每日最新资讯28at.com

但是,未来可能不再需要这些替代方案和第三方包。现在有一个 活跃的提案 - 还包括一个旨在改进 ServeMux 参考实现 ,使其能够匹配 HTTP 方法和通配符路径。asQ28资讯网——每日最新资讯28at.com

Google 的 Go 团队成员 Jonathan Amsterdam 主导了这个提案以及之前的 讨论。Jonathan 曾成功提出将结构化日志添加到标准库的提案 - Go 1.21 将包含他的log/slog包(预计 2023 年 8 月发布)。asQ28资讯网——每日最新资讯28at.com

现状与变革

在目前的情况下,如果想将 GET 请求匹配到 /users/{user}/settings,你需要编写以下的样板代码(尽管在实践中你可能会使用第三方库):asQ28资讯网——每日最新资讯28at.com

mux.HandleFunc("/users/", func(w http.ResponseWriter, r *http.Request) {    if r.Method != "GET" {        http.Error(w, "method not allowed", http.StatusMethodNotAllowed)        return    }    remainder := r.URL.Path[len("/users/"):]    userId, subPath, _ := strings.Cut(remainder, "/")    switch subPath {    case "settings":        fmt.Fprintf(w, "user %s", userId)    // 其他子路径可以在这里添加    default:        http.NotFound(w, r)    }})

如果接受了这个提议,你可以更加简单地实现一样的功能:asQ28资讯网——每日最新资讯28at.com

mux.HandleFunc("GET /users/{user}/settings", func(w http.ResponseWriter, r *http.Request) {    fmt.Fprintf(w, "user %s", r.PathValue("user"))})

这样的写法明显更为简洁!asQ28资讯网——每日最新资讯28at.com

这与其他流行路由器使用的语法非常相似:asQ28资讯网——每日最新资讯28at.com

// github.com/go-chi/chirouter.Get("/users/{user}/settings", func(w http.ResponseWriter, r *http.Request) {    fmt.Fprintf(w, "user %s", chi.URLParam(r, "slug"))})// github.com/gorilla/muxrouter.HandleFunc("/users/{user}/settings", func(w http.ResponseWriter, r *http.Request) {    fmt.Fprintf(w, "user %s", mux.Vars(r)["user"])}).Methods("GET")// github.com/bmizerany/patrouter.Get("/users/:user/settings", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {    fmt.Fprintf(w, "user %s", r.URL.Query().Get(":user"))}))// github.com/gin-gonic/ginrouter.GET("/users/:user/settings", func(c *gin.Context) {    fmt.Fprintf(w, "user %s", c.Param("user"))})

提案中的一个有趣决定是,并没有为 ServeMux 添加新的方法;而是对现有的 Handle  HandleFunc 方法进行了扩展,以支持方法前缀和 {wildcard} 路径段。asQ28资讯网——每日最新资讯28at.com

我理解他们避免添加新方法的想法,但我对这个决定持保留态度。遗憾的是,旧版的 ServeMux 接受如 Handle("GET /foo", h) 的模式。这意味着为增强版 ServeMux 编写的代码将在旧版 Go 上能正常编译和运行,但路由不会匹配到任何内容,这容易导致错误。我可能会添加新的方法,比如 HandleMatch / HandleMatchFunc 或 Route / RouteFunc。asQ28资讯网——每日最新资讯28at.com

该提议也详细描述了处理两个重叠模式的优先级,其核心规则简单明了:“如果两个模式有重叠(有共同的请求),则更具体的模式优先匹配”。asQ28资讯网——每日最新资讯28at.com

例如,如果你注册了模式 /users/(匹配 /users/*)以及模式 /users/{user},当一个 /users/ben 的请求进来时,它将匹配第二个,更具体的模式。这与现有的 ServeMux 中,特定主机的模式优先于没有主机名的模式的行为一致。asQ28资讯网——每日最新资讯28at.com

URL 末尾通配符匹配

此提案为我们带来了一个新的"特殊通配符" {$},它专门用于匹配 URL 的末尾。对于那些仅希望匹配主页路由的情况,这个新特性显得非常实用。在此之前,要实现这一目标颇为麻烦,因为以 / 结尾的模式会匹配所有 / 之下的内容;这个规则对于只有 / 的模式同样适用。asQ28资讯网——每日最新资讯28at.com

因此,以前若想匹配主页,你需要这样操作:asQ28资讯网——每日最新资讯28at.com

mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {    if r.URL.Path != "/" { // 确保路径就是 "/"        http.NotFound(w, r)        return    }    serveHomepage(w, r)})mux.HandleFunc("/users", serveUsers)

这一过程颇为繁琐。若你忘记了路径检查,那么你最终可能会将主页用于所有其他的 URL,而不是显示一个未找到的页面,因为所有的内容都在 / 之下。asQ28资讯网——每日最新资讯28at.com

而根据新的提案,这个过程将变得更加简洁:asQ28资讯网——每日最新资讯28at.com

mux.HandleFunc("/{$}", serveHomepage)mux.HandleFunc("/users", serveUsers)

实现参考

Jonathan 在 github.com/jba/muxpatterns 中发布了一个 ServeMux 的增强版本的示例实现。唯一的区别在于,由于它是在单独的包中,无法改变 http.Request 类型, 所以你需要用 mux.PathValue(request, "name") 来获取路径值,而非 request.PathValue("name")。asQ28资讯网——每日最新资讯28at.com

我在 我的 go-routing 仓库 中添加了一个 PR,这个 PR 提供了我自己的 widget API 的一种实现,使用 muxpatterns。这个版本与 chi 版本 非常相似 —— 清晰且易读:asQ28资讯网——每日最新资讯28at.com

r.HandleFunc("GET /{$}", home)r.HandleFunc("GET /contact", contact)r.HandleFunc("GET /api/widgets", apiGetWidgets)r.HandleFunc("POST /api/widgets", apiCreateWidget)r.HandleFunc("POST /api/widgets/{slug}", apiUpdateWidget)r.HandleFunc("POST /api/widgets/{slug}/parts", apiCreateWidgetPart)r.HandleFunc("POST /api/widgets/{slug}/parts/{id}/update", apiUpdateWidgetPart)r.HandleFunc("POST /api/widgets/{slug}/parts/{id}/delete", apiDeleteWidgetPart)r.HandleFunc("GET /{slug}", widgetGet)r.HandleFunc("GET /{slug}/admin", widgetAdmin)r.HandleFunc("POST /{slug}/image", widgetImage)

当我首次测试这个参考实现时,我发现了一些小问题,现已得到修复。asQ28资讯网——每日最新资讯28at.com

结论

尽管我对于扩展现有的 Handle 和 HandleFunc 方法有一些保留,但我对这个提案的考虑感到欣慰。鉴于 Jonathan 在提案中的谨慎处理、他在 log/slog 上的良好表现以及社区的积极反馈,此提案被接受的可能性很高。asQ28资讯网——每日最新资讯28at.com

如果这个功能能进入标准库,那将非常棒 —— 我开发的几乎所有网站和 REST 风格的 API 都将用到这个功能。Go 的标准库已经非常强大,但加入这个功能将进一步减少对第三方路由器的依赖。asQ28资讯网——每日最新资讯28at.com

如果这个功能能够集成在 2024 年 2 月发布的 Go 1.22 中,我并不会感到惊讶。让我们拭目以待!asQ28资讯网——每日最新资讯28at.com

译者介绍

刘汪洋,51CTO社区编辑,昵称:明明如月,一个拥有 5 年开发经验的某大厂高级 Java 工程师,拥有多个主流技术博客平台博客专家称号。asQ28资讯网——每日最新资讯28at.com

原文标题:The proposal to enhance Go’s HTTP router,作者:Ben HoytasQ28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-5719-0.html提升Go的HTTP路由器的提案

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: SpringBoot使用WebSocket实现即时消息

下一篇: 穿上App外衣,保持Web灵魂——PWA温故

标签:
  • 热门焦点
  • 对标苹果的灵动岛 华为带来实况窗功能

    继苹果的灵动岛之后,华为也在今天正式推出了“实况窗”功能。据今天鸿蒙OS 4.0的现场演示显示,华为的实况窗可以更高效的展现出实时通知,比如锁屏上就能看到外卖、打车、银行
  • 直屏旗舰来了 iQOO 12和K70 Pro同台竞技

    旗舰机基本上使用的都是双曲面屏幕,这就让很多喜欢直屏的爱好者在苦等一款直屏旗舰,这次,你们等到了。据博主数码闲聊站带来的最新爆料称,Redmi下代旗舰K70 Pro和iQOO 12两款手
  • 企业采用CRM系统的11个好处

    客户关系管理(CRM)软件可以为企业提供很多的好处,从客户保留到提高生产力。  CRM软件用于企业收集客户互动,以改善客户体验和满意度。  CRM软件市场规模如今超过580
  • 每天一道面试题-CPU伪共享

    前言:了不起:又到了每天一到面试题的时候了!学弟,最近学习的怎么样啊 了不起学弟:最近学习的还不错,每天都在学习,每天都在进步! 了不起:那你最近学习的什么呢? 了不起学弟:最近在学习C
  • 零售大模型“干中学”,攀爬数字化珠峰

    文/侯煜编辑/cc来源/华尔街科技眼对于绝大多数登山爱好者而言,攀爬珠穆朗玛峰可谓终极目标。攀登珠峰的商业路线有两条,一是尼泊尔境内的南坡路线,一是中国境内的北坡路线。相
  • 花7万退货退款无门:谁在纵容淘宝珠宝商家造假?

    来源:极点商业作者:杨铭在淘宝购买珠宝玉石后,因为保证金不够赔付,店铺关闭,退货退款难、维权无门的比比皆是。“提供相关产品鉴定证书,支持全国复检,可以30天无理由退换货。&
  • 小米MIX Fold 3配置细节曝光:搭载领先版骁龙8 Gen2+罕见5倍长焦

    这段时间以来,包括三星、一加、荣耀等等有不少品牌旗下的最新折叠屏旗舰都得到了不少爆料,而小米新一代折叠屏旗舰——小米MIX Fold 3此前也屡屡被传
  • iQOO Neo8 Pro真机谍照曝光:天玑9200+和V1+旗舰双芯加持

    去年10月,iQOO推出了iQOO Neo7系列机型,不仅搭载了天玑9000+,而且是同价位唯一一款天玑9000+直屏旗舰,一经上市便受到了用户的广泛关注。在时隔半年后,
  • 由于成本持续增加,笔记本产品价格预计将明显上涨

    根据知情人士透露,由于材料、物流等成本持续增加,笔记本产品价格预计将在2021年下半年有明显上涨。进入6月下旬以来,全球半导体芯片缺货情况加剧,显卡、处理器
Top