gin-gonic / gin

Gin is a HTTP web framework written in Go (Golang). It features a Martini-like API with much better performance -- up to 40 times faster. If you need smashing performance, get yourself some Gin.
https://gin-gonic.com/
MIT License
77.68k stars 7.95k forks source link

Middleware doesn't apply to Redirect #1985

Open xdays opened 5 years ago

xdays commented 5 years ago

Here's sample code:

package main

import (
    "net/http"

    "github.com/gin-gonic/gin"
)

//CORSMiddleware ...
func CORSMiddleware() gin.HandlerFunc {
    return func(c *gin.Context) {
        c.Writer.Header().Set("Access-Control-Allow-Origin", "http://localhost")
        c.Writer.Header().Set("Access-Control-Max-Age", "86400")
        c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE")
        c.Writer.Header().Set("Access-Control-Allow-Headers", "X-Requested-With, Content-Type, Origin, Authorization, Accept, Client-Security-Token, Accept-Encoding, x-access-token")
        c.Writer.Header().Set("Access-Control-Expose-Headers", "Content-Length")
        c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")

        if c.Request.Method == "OPTIONS" {
            c.AbortWithStatus(200)
        } else {
            c.Next()
        }
    }
}

func main() {
    r := gin.Default()
    r.Use(CORSMiddleware())
    g := r.Group("/users")

    g.GET("/", func(context *gin.Context) {
        context.JSON(http.StatusOK, gin.H{"hello": "world"})
    })

    r.Run(":8081")
}

Here's normal response with CORS headers.

curl -v localhost:8081/users/                                                       <aws:loop-staging>
*   Trying ::1:8081...
* TCP_NODELAY set
* Connected to localhost (::1) port 8081 (#0)
> GET /users/ HTTP/1.1
> Host: localhost:8081
> User-Agent: curl/7.65.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Access-Control-Allow-Credentials: true
< Access-Control-Allow-Headers: X-Requested-With, Content-Type, Origin, Authorization, Accept, Client-Security-Token, Accept-Encoding, x-access-token
< Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE, UPDATE
< Access-Control-Allow-Origin: http://localhost
< Access-Control-Expose-Headers: Content-Length
< Access-Control-Max-Age: 86400
< Content-Type: application/json; charset=utf-8
< Date: Fri, 12 Jul 2019 06:27:16 GMT
< Content-Length: 18
<
{"hello":"world"}
* Connection #0 to host localhost left intact

But my CORS header doesn't apear in the 301 redirect response

[14:27] ➜  ~ curl -v localhost:8081/users                                                        <aws:loop-staging>
*   Trying ::1:8081...
* TCP_NODELAY set
* Connected to localhost (::1) port 8081 (#0)
> GET /users HTTP/1.1
> Host: localhost:8081
> User-Agent: curl/7.65.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 301 Moved Permanently
< Content-Type: text/html; charset=utf-8
< Location: /users/
< Date: Fri, 12 Jul 2019 06:27:19 GMT
< Content-Length: 42
<
<a href="/users/">Moved Permanently</a>.

* Connection #0 to host localhost left intact
Louis-Amas commented 4 years ago

Same here did you find a fix?

xdays commented 4 years ago

My solution is not using api group for /users to avoid 301 redireciton.

lolgolflol commented 3 years ago
g.GET("", func(context *gin.Context) {
        context.JSON(http.StatusOK, gin.H{"hello": "world"})
    })

Try to use this code.

tangx commented 2 years ago

still have this problem.

tangx commented 2 years ago

and gin, for the present, call middleware after router finding.

https://github.com/gin-gonic/gin/issues/2413

        rg.GET("/", func(c *gin.Context) {
            _url := strings.TrimRight(c.Request.URL.Path, "/") + "?" + c.Request.URL.RawQuery
            c.Redirect(301, _url)
        })

it's ugly, but it works

timqian commented 1 year ago

Any updates on this issue?

yashvardhan-kukreja commented 6 months ago

Raised a fix here - https://github.com/gin-gonic/gin/pull/3858

You can directly start using it in your project by running this

go mod edit -replace="github.com/gin-gonic/gin=github.com/yashvardhan-kukreja/gin@issue-3857-onredirect-middleware"  && GOPROXY=direct go get -d ./...