0

我正在寻找一种干净的方法来维护具有相同端点的 API 的两个版本。

现在,最简单但似乎过度的方法是拥有类似的东西

  r := chi.NewRouter()
  r.Get("/test", func(w http.ResponseWriter, r *http.Request) {
    version := r.Header.Get("Accept-version")
    if version == "v1" {
      w.Write([]byte("version 1 of api"))
    } else {
      w.Write([]byte("other version of api"))
    }
  })

但是当你有几十个左右的端点时......可能会变得混乱

我想要它的方式是有一个中间件,它将通过下一个定义的路线。所以像

  r := chi.NewRouter()
  r.With(UseVersion1).Get("/test", func(w http.ResponseWriter, r *http.Request) {
      w.Write([]byte("version 1 of api"))
    }
  })
  r.With(UseVersion2).Get("/test", func(w http.ResponseWriter, r *http.Request) {
      w.Write([]byte("other version of api"))
    }
  })

这甚至可能吗?或者有人可以建议一条更好的路线(双关语不是故意的)

编辑:我知道为路径添加前缀是一个可行的选择。我想避免这种情况

4

1 回答 1

0

alexmac is right Usually we uses prefix, also, you can uses midleware if you do't want to add prefix(ps:Not recommended)

your code have a problem, one url can't use many midleware

follow is a example in gin, in chi , you can write yourself code:

package main

import (
    "github.com/gin-gonic/gin"
)

func Version() gin.HandlerFunc {
    return func(c *gin.Context) {

        if c.Request.RequestURI[:2] != "/v" {
            version := c.GetHeader("Accept-version")
            if version == ""{
                version = "v2"
            }
            c.Redirect(302, "/" + version + c.Request.RequestURI)
            c.Abort()
        }else{
            c.Next()
        }
    }
}

func main() {
    r := gin.New()
    r.Use(Version())
    v1 := r.Group("v1")
    v2 := r.Group("v2")

    v1.GET("/test", func (c *gin.Context){
        c.String(200, "v1 test")
    })
    v2.GET("/test", func (c *gin.Context){
        c.String(200, "v2 test")
    })

    // Listen and serve on 0.0.0.0:8080
    r.Run(":8080")
}

if you don't want to chagne the url you can:

package main

import (
    "github.com/gin-gonic/gin"
)
var(
    r *gin.Engine
)
func Version() gin.HandlerFunc {
    return func(c *gin.Context) {
        if c.Request.URL.Path[:2] != "/v" {
            version := c.GetHeader("Accept-version")
            if version == ""{
                version = "v2"
            }
            c.Request.URL.Path = "/" + version + c.Request.RequestURI
            r.HandleContext(c)
            c.Abort()
        }
        c.Next()
    }
}

func main() {
    r = gin.New()
    r.Use(Version())
    v1 := r.Group("v1")
    v2 := r.Group("v2")
    v1.GET("/test", func (c *gin.Context){
        c.String(200, "v1/test")
    })
    v2.GET("/test", func (c *gin.Context){
        c.String(200, "v2/test")
    })

    // Listen and serve on 0.0.0.0:8080
    r.Run(":8080")
}

于 2021-08-24T08:08:41.227 回答