英文:
Can't change POST request to GET request using Gin/GoLang
问题
我似乎无法在Gin框架中将POST方法更改为GET方法。当我收到一个请求时,我想要检查其凭据,如果有效,就重定向到另一个具有GET端点的页面。无论我使用c.Request.Method="GET"
,它似乎只会更改当前端点的请求,但重定向后的请求仍然保持原始方法,即POST方法。
代码:
auth.GET("/sign-in", func(c *gin.Context) {
c.File("../../html/index.html")
})
auth.POST("/sign-in", func(c *gin.Context) {
c.Request.Method = "GET"
c.Redirect(http.StatusTemporaryRedirect, "/profile/:pid")
})
Code 307
请求最初是POST
请求,由端点本身更改为GET
。
使用c.Request.Method="GET"
没有帮助。我也找不到答案。有什么办法可以改变这种行为吗?创建一个新的请求是唯一的解决方案吗?
英文:
I seem to not be able to change POST method with GET method in Gin Framework. When I receive a request, I want to check credentials of it and, if valid, redirect to another page, which has a GET endpoint. Whenever I use c.Request.Method="GET"
it seems to change request only for the current endpoint, but redirected one still has the original method, i.e. POST method.
Code:
auth.GET("/sign-in", func(c *gin.Context) {
c.File("../../html/index.html")
})
auth.POST("/sign-in", func(c *gin.Context) {
c.Request.Method = "GET"
c.Redirect(http.StatusTemporaryRedirect, "/profile/:pid")
})
Code 307
request is originally POST
request, changed to GET
by the endpoint itself.
Doing c.Request.Method="GET"
didn't help. Couldn't find answer either. Any idea how to change this behavior? Is creating a new request the only solution?
答案1
得分: 2
307状态码文档中提到:
> 重定向请求时,原始请求的方法和主体将被重用。如果你希望将使用的方法更改为GET,请使用303 See Other。
因此,如果你将http.StatusTemporaryRedirect
更改为http.StatusSeeOther
,它将在不更改原始请求方法的情况下工作。
英文:
307 status code documentation says:
> The method and the body of the original request are reused to perform the redirected request. In the cases where you want the method used to be changed to GET, use 303 See Other instead.
So if you change http.StatusTemporaryRedirect
to http.StatusSeeOther
, it will work without changing the original request method.
答案2
得分: 1
你是正确的,将 c.Request.Method = "GET"
设置在 POST
端点中只会改变该端点的方法,而在重定向中发送的请求的方法仍然是 POST
。
实现所需行为的正确方法是使用 c.Request.Method
设置方法,但不是使用 Redirect
(它只适用于当前请求),而是使用 c.HTML
进行重定向,它会发起一个新的请求,并使用你设置的正确方法渲染你想要访问的新端点。
你提到的 http.StatusSeeOther
状态码在这种情况下也是正确的,因为它表示资源已被临时移动,客户端应使用 Location 头字段中提供的新 URI 访问资源。
所以你的代码可以像这样写:
auth.POST("/sign-in", func(c *gin.Context) {
c.Request.Method = "GET"
c.HTML(http.StatusSeeOther, "profile/:pid", nil)
})
这样,你就可以使用新的请求重定向到新位置,并使用你想要的方法。
英文:
You're correct that setting c.Request.Method = "GET"
in the POST
endpoint will only change the method for that endpoint, and the method of the request being sent in the redirect will still be POST
.
The correct way to achieve the desired behavior is to use the c.Request.Method
to set the method but instead of using Redirect
which is specific to the current request you should redirect with c.HTML
which makes a new request and renders the new endpoint you want to visit using the correct method you set.
The http.StatusSeeOther
status code you are mentioning is also the correct one to use in this case, as it indicates that the resource has been temporarily moved, and the client should use the new URI provided in the Location header field to access the resource.
So your code could look like this:
auth.POST("/sign-in", func(c *gin.Context) {
c.Request.Method = "GET"
c.HTML(http.StatusSeeOther, "profile/:pid", nil)
})
This way you are redirecting to the new location but with a new request, with the method you desire.
答案3
得分: 0
Go按顺序读取端点,所以如果它遇到一个GET请求,它不会再为同一个端点搜索另一个GET请求。最高优先级的请求会胜出。据我所知,我可能在这里错了。但是...
如果你将逻辑更改为以下内容,会怎样呢?
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-html -->
auth.POST("/sign-in", func(c *gin.Context) {
c.Request.Method = "GET"
// Serve the index -page
// Implement the credential check logic here
// Perform validation
...
isValidUser, _ := checkCredentials(user.Username, user.Password)
if isValidUser {
c.Redirect(http.StatusTemporaryRedirect, "/profile/:pid")
}
...
})
<!-- end snippet -->
使用这种逻辑,并从这里继续 - 同时完全删除第一个GET请求。
注意:这不是有效的代码,只是一些你可以继续的想法。
英文:
Go reads the endpoints procedurally, so if it hits a GET -request, it will not search for another GET -request for the same endpoint. The most "highest" one wins. AFAIK, I might be wrong here. But ...
What if you change the logic to something like following?
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-html -->
auth.POST("/sign-in", func(c *gin.Context) {
c.Request.Method = "GET"
// Serve the index -page
// Implement the credential check logic here
// Perform validation
...
isValidUser, _ := checkCredentials(user.Username, user.Password)
if isValidUser {
c.Redirect(http.StatusTemporaryRedirect, "/profile/:pid")
}
...
})
<!-- end snippet -->
With this logic and continue from here - while dropping the first GET -request altogether.
Note: This is not valid code, just ideas how you could proceed.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论