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?
CodePudding user response:
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.
CodePudding user response:
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.
CodePudding user response:
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.