Gin框架作为一个轻量级的Web框架,其路由基本原理就是构造一个路由地址的前缀树,路由使用的是httprouter这个库。
func main() {
r := gin.Default()
r.GET("/login/:username/:password", func(c *gin.Context) {
username := c.Param("username")
password := c.Param("password")
c.String(http.StatusOK, "%s,%s", username, password)
})
r.GET("/user/:name/*age", func(c *gin.Context) {
name := c.Param("name")
age := c.Param("age")
c.JSON(http.StatusOK, gin.H{
"name": name,
"age": age,
})
})
r.Run(":8080")
}
r.GET("/index", func(c *gin.Context) {...})
r.POST("/index", func(c *gin.Context) {...})
r.PUT("/index", func(c *gin.Context) {...})
r.DELETE("/index", func(c *gin.Context) {...})
//等等
此外,还有一个可以匹配所有请求方法的Any方法如下:
r.Any("/index", func(c *gin.Context) {//TODO})
还可以为没有匹配处理函数的路由添加处理程序,默认情况下它返回404代码,下面的代码为没有匹配到路由的请求都返回404.html页面。
r.NoRoute(func(c *gin.Context) {
c.HTML(http.StatusNotFound, "404.html", nil)
})
将拥有共同URL前缀的路由划分为一个路由组。习惯性一对{ }包裹同组的路由,这只是为了看着清晰,本质上用不用{ }包裹,其功能上没什么区别。官方文档示例代码如下:
// 简单的路由组: v1
v1 := router.Group("/v1")
{
v1.POST("/login", loginEndpoint)
v1.POST("/submit", submitEndpoint)
}
// 简单的路由组: v2
v2 := router.Group("/v2")
{
v2.POST("/login", loginEndpoint)
v2.POST("/submit", submitEndpoint)
}
其中路由组也是支持嵌套的,示例代码如下:
shopping := r.Group("/shop")
{
shopping.GET("/index", shop)
// 嵌套路由组
view := shopping.Group("view")
view.GET("/home", view)
}
通常会将路由分组用在划分业务逻辑或划分API版本时。
3XX 状态码是关于重定向的,常见的状态码有:301,302,303,304,307 和 308。这些状态码大致可以分为三类,其中包括:
永久重定向:是指用户请求的资源地址已经废弃了,现在需要使用新地址来访问,并通过响应 Header 的 Location 字段将这个新的地址告知给用户。
就好比胡同口有一家我们常去的饭店,但是由于旧城改造这家店搬迁到了另一个地方。有一天我们准备去这家店吃饭,发现门口张贴告示:此店已迁移到 XXX,并附上了详细的新地址。也就是说,之后如果我还想去这家店吃饭,只能去新的地址。
如果浏览器发送的是GET请求,301和308没有区别。但如果是POST请求,会有以下区别
临时重定向:由于某些原因,导致用户请求的资源地址临时不可用,但其他某个地址是可访问的,于是就通过响应 Header 的 Location 字段将这个临时地址告知给用户。
就好比我们去一家饭店吃饭,到门口发现老板张贴告示:家里临时有事,请去附近另一个分店用餐,并附上了分店的详细地址。这样,我们就可以先临时去这家分店用餐,等之后老板回来了,我们又可以在原来这家店继续用餐。
为什么永久重定向是两个状态码,而临时重定向却有三个状态码,这是与http协议的发展历史有很大关系。
在 http1.0 时期:
文档规定:浏览器第一次请求的方法要和重定向时候的请求方法保持一致。
在浏览器实现上:若用户第一次为 POST 请求,浏览器询问用户是否向新 URL 发送请求,并强制使用 GET发送第二个请求(与文档规定有所差异)。
在http1.1 时期:
为了弥补 http1.0 时期文档中 302 和浏览器实现上 302 的偏差,这才逐渐补充了303和307的状态码。
StatusMultipleChoices = 300 // RFC 9110, 15.4.1
StatusMovedPermanently = 301 // RFC 9110, 15.4.2
StatusFound = 302 // RFC 9110, 15.4.3
StatusSeeOther = 303 // RFC 9110, 15.4.4
StatusNotModified = 304 // RFC 9110, 15.4.5
StatusUseProxy = 305 // RFC 9110, 15.4.6
_ = 306 // RFC 9110, 15.4.7 (Unused)
StatusTemporaryRedirect = 307 // RFC 9110, 15.4.8
StatusPermanentRedirect = 308 // RFC 9110, 15.4.9
r.GET("/test1", func(c *gin.Context) {
c.Redirect(http.StatusMovedPermanently, "https://www.baidu.com")
})
r.GET("/test2", func(c *gin.Context) {
c.Request.URL.Path = "/test3" //在上下文中改变路由的路径
r.HandleContext(c) //把修改后的上下文写入到路由中
})
r.GET("/test3", func(c *gin.Context) {
c.JSON(http.StatusOK,gin.H{"msg":"This is /test3"})
})