gin、httprouter 的路由冲突
在使用 gin 做 api 开发的时候,遇到了路由冲突的情况。这里记录下冲突的原因,以及解决方案。
场景
在开发一个查看文章的 api 时,设计了如下的路由:
1 | r := gin.Default() |
结果程序会发生 painc,提示路由冲突。
原因
路由冲突的原因,主要是由于 gin 采用了 httprouter 作为路由,如果两个路由的 http method 相同,并且请求路径的前缀相同,如果出现了 /:id /hot 这样的 path,则会产生冲突。
在以前使用的 web 框架中,当出现上面的情况时,一般都会优先匹配 /hot ,然后在进行匹配 /:id,会有一个优先级的判断,但是在 gin 的路由中没有这种处理方案。
httprouter 使用 radix tree 结构来存储路由,保证查证路由时的性能。
/posts 作为其中的一个节点,当 :id 被注册到子节点之后,再次注册 hot 时,程序会判定与 /:id 产生冲突,不能注册。
解决方案
第一种
变化单复数形式,当使用 :id 时,将 /posts/:id 改为 /post/:id
1 | r := gin.Default() |
第二种
只保留一条路由,在 handler 中分情况处理。如下
1 | r := gin.Default() |