简体   繁体   中英

Can't change POST request to GET request using Gin/GoLang

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, ie 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?

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.

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.

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?

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM