处理完GET请求后,我想将用户重定向到由我的应用程序处理的新URL,该URL会显示结果.

gin documentation中,我发现了两种不同的方法来做到这一点.一个是使用gin的redirect()功能,另一个是使用它的路由HandleContext()功能.引用的文档称redirect()应用于Post请求或GET请求,但随后又称HandleContext()应用于"Router"重定向.我不确定我完全理解使用其中一种的含义.

上面引用的文档中给出的第一个用例是:

r.GET("/test", func(c *gin.Context) {
    c.Redirect(http.StatusMovedPermanently, "http://www.google.com/")
})

这里似乎不同的是,重定向是到外部URL,远离我的应用程序本身.第二个用例被描述为"路由重定向",是:

r.GET("/test", func(c *gin.Context) {
    c.Request.URL.Path = "/test2"
    r.HandleContext(c)
})
r.GET("/test2", func(c *gin.Context) {
    c.JSON(200, gin.H{"hello": "world"})
})

因此,如果重定向的URL是我的应用程序处理的路径,这似乎是必需的.

但这是一个像任何其他URL一样的URL.那么为什么不直接使用c.redirect()进行路由重定向呢?

直觉上,这是显而易见的事情.但我怀疑它会产生意想不到的行为(或者至少是我个人没有想到的行为)

使用c.redirect()进行路由重定向有什么问题?它和router.HandleContext()有什么区别?

推荐答案

不同之处在于,HandleContext()执行客户端从未注意到的internal redirection,而Redirect()实际上向https客户端发送响应,通知其资源已更改.

我认为通过观察浏览器的DevTools可以最好地说明这一点.

HandleContext(): HandleContext As you can see, here the client never even noticed that the request was redirected to another handler internally.

Redirect(): redirect Here the client was forced to make two requests to get the actual resource. Also notice that the URL bar now displays the URL of the redirected request.

显然是two requests leads to worse performance,这就是为什么内部重定向应该首选router.HandleContext().

如果您想测试自己,请参阅以下代码:

package main

import (
    "net/http"

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

func main() {
    r := gin.Default()

    // Switch the uncommented block in order to see the effect of HandleContext.
    /* r.GET("/test", func(c *gin.Context) {
        c.Request.URL.Path = "/test2"
        r.HandleContext(c)
    })
    r.GET("/test2", func(c *gin.Context) {
        c.JSON(200, gin.H{"hello": "world"})
    }) */

    r.GET("/test", func(c *gin.Context) {
        c.Redirect(http.StatusMovedPermanently, "/test2")
    })
    r.GET("/test2", func(c *gin.Context) {
        c.JSON(200, gin.H{"hello": "world"})
    })

    r.Run()
}

Go相关问答推荐

Golang socks 5代理,流量限制转发到下一个socks 5代理

如何禁用Go SRC包中的VSCode警告?

"k8s.io/apimachinery/pkg/runtime.对象(缺少方法DeepCopyBody)

Go 1.22 net/http群组路由

如何预编译Golang标准库?

正确使用pgtype的方法

从 ApiGateway 中的 lambda Go 返回 Json

用 fork 替换 Go 依赖:...用于两个不同的模块路径

从给定顶点查找图形中所有闭合路径的算法

当填充通道的函数调用未嵌入 goroutine 时,为什么我会遇到死锁?

判断一个区域内的纬度/经度点

泛型:实现嵌套接口

regex.ReplaceAll 但如果替换则添加相同数量的字符

Go 信号处理程序不处理终端窗口关闭

Golang 通过接口反映/迭代{}

如何过滤来自 fsnotify 的重复系统消息

golang pic.ShowImage 为什么它不生成图像而是向我发送base64值

GqlGen - 在字段解析器中访问查询输入参数

函数超时和 goroutine 泄漏

获取单调时间,同 CLOCK_MONOTONIC