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

  1. setup gin server with post api, the post api will be redirect.
  2. the post api handler will be processed by context.Redirect() with json content.
  3. 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