无法使用Gin/GoLang将POST请求更改为GET请求。

huangapple go评论85阅读模式
英文:

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")
})

无法使用Gin/GoLang将POST请求更改为GET请求。

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")
})

无法使用Gin/GoLang将POST请求更改为GET请求。

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(&quot;/sign-in&quot;, func(c *gin.Context) {
    c.Request.Method = &quot;GET&quot;

    // Serve the index -page

    // Implement the credential check logic here

    // Perform validation

    ...

    isValidUser, _ := checkCredentials(user.Username, user.Password)

    if isValidUser {
      c.Redirect(http.StatusTemporaryRedirect, &quot;/profile/:pid&quot;)    
    }

    ...
})

<!-- 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.

huangapple
  • 本文由 发表于 2023年1月11日 18:56:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/75081950.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定