I found this one before I opened a new issue: https://github.com/gin-gonic/gin/issues/712 But it can't be successfully redirected by http 307 or 308 based on the description. I think there is something wrong with it.
Also I found this one: https://github.com/bear0412/go-gin/commit/06cb92f8c4d58f80cd038b6e9b5f697ce75a77a7 But it also can't be successfully be redirected.
Description
- setup gin server with post api, the post api will be redirect.
- the post api handler will be processed by context.Redirect() with json content.
- the json content not be processed properly.
How to reproduce
Run the below code:
package main
import (
"fmt"
"net/http"
"github.com/gin-gonic/gin"
)
// album represents data about a record album.
type album struct {
ID string `json:"id"`
Title string `json:"title"`
Artist string `json:"artist"`
Price float64 `json:"price"`
}
// albums slice to seed record album data.
var albums = []album{
{ID: "1", Title: "Blue Train", Artist: "John Coltrane", Price: 56.99},
{ID: "2", Title: "Jeru", Artist: "Gerry Mulligan", Price: 17.99},
{ID: "3", Title: "Sarah Vaughan and Clifford Brown", Artist: "Sarah Vaughan", Price: 39.99},
}
func main() {
router := gin.Default()
router.GET("/albums", getAlbums)
router.GET("/albums/:id", getAlbumByID)
router.POST("/albums", postAlbums)
router.GET("/update", updateAlbums)
router.Run("localhost:8080")
}
// getAlbums responds with the list of all albums as JSON.
func getAlbums(c *gin.Context) {
c.IndentedJSON(http.StatusOK, albums)
}
func updateAlbums(c *gin.Context) {
fmt.Println("redirect:")
var newAlbum album
if err := c.BindJSON(&newAlbum); err != nil {
fmt.Println("redirect: error in bind")
return
}
fmt.Println(newAlbum)
albums[0] = newAlbum
fmt.Println(albums)
c.IndentedJSON(200, albums)
}
// postAlbums adds an album from JSON received in the request body.
func postAlbums(c *gin.Context) {
var newAlbum album
// Call BindJSON to bind the received JSON to
// newAlbum.
if err := c.BindJSON(&newAlbum); err != nil {
return
}
// fmt.Println(newAlbum)
c.Redirect(307, "/update")
// Add the new album to the slice.
// albums = append(albums, newAlbum)
// c.IndentedJSON(http.StatusCreated, newAlbum)
}
// getAlbumByID locates the album whose ID value matches the id
// parameter sent by the client, then returns that album as a response.
func getAlbumByID(c *gin.Context) {
id := c.Param("id")
// Loop through the list of albums, looking for
// an album whose ID value matches the parameter.
for _, a := range albums {
if a.ID == id {
c.IndentedJSON(http.StatusOK, a)
return
}
}
c.IndentedJSON(http.StatusNotFound, gin.H{"message": "album not found"})
}
Expectations
$ curl -vvv localhost:8080/albums --header "Content-Type: application/json" --request POST --data '{"id":"4", "title":"hello", "price":28.5}'
will be processed and the debug log in the redirected api will be printed.
Actual result
$ curl -vvv localhost:8080/albums --header "Content-Type: application/json" --request POST --data '{"id":"4", "title":"hello", "price":28.5}' 08:58:42 PM
Note: Unnecessary use of -X or --request, POST is already inferred.
* Trying 127.0.0.1:8080...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> POST /albums HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.85.0
> Accept: */*
> Content-Type: application/json
> Content-Length: 41
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 308 Permanent Redirect
< Location: /update
< Date: Mon, 06 Mar 2023 12:58:45 GMT
< Content-Length: 0
<
* Connection #0 to host localhost left intact
and no print in the redirected api
Environment
- go version: go version go1.19.3 darwin/arm64
- gin version (or commit ref): d07db174acf44bfaf191ca2f6d7beafa2ff946da
- operating system: Darwin m1.local 22.2.0 Darwin Kernel Version 22.2.0
Comment From: rnotorni
Could you check -L
option in curl?
e. x.
curl -vvv -L localhost:8080/albums --header "Content-Type: application/json" --request POST --data '{"id":"4", "title":"hello", "price":28.5}'
I think it's a client side problem that it doesn't redirect
Comment From: WinnieeBear
resolved. Thanks.
Comment From: WinnieeBear
Could you check
-L
option in curl?e. x.
curl -vvv -L localhost:8080/albums --header "Content-Type: application/json" --request POST --data '{"id":"4", "title":"hello", "price":28.5}'
I think it's a client side problem that it doesn't redirect
By the way not sure the the Chrome or FireFox will redirect the request by default like the curl with -L option. Can you confirm?
Comment From: rnotorni
If HttpStatus is in the 300 range and Location is set, redirect is done by default.
If anything, we should be careful not to consider the redirect to be a loop.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Redirections