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
78.96k stars 8.02k forks source link

Use built-in graceful mode, can not read client ip from "X-Forwarded-For" header #2693

Open walnut-tom opened 3 years ago

walnut-tom commented 3 years ago

Use built-in graceful mode, can not read client ip from "X-Forwarded-For" header.

How to reproduce

set The engine.TrustedProxies already set to []string{"127.0.0.0/8", "192.168.0.0/16", "172.16.0.0/12", "10.0.0.0/8"} but client ip is not read from "X-Forwarded-For".

// +build go1.8

package main

import (
    "context"
    "errors"
    "log"
    "net/http"
    "os"
    "os/signal"
    "syscall"
    "time"

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

func main() {
    router := gin.Default()
    router.GET("/", func(c *gin.Context) {
        time.Sleep(5 * time.Second)
        c.String(http.StatusOK, "Welcome Gin Server; Client IP is: "+c.ClientIP())
    })

    router.TrustedProxies = []string{"127.0.0.0/8", "192.168.0.0/16", "172.16.0.0/12", "10.0.0.0/8"}

    srv := &http.Server{
        Addr:    ":8080",
        Handler: router,
    }

    // Initializing the server in a goroutine so that
    // it won't block the graceful shutdown handling below
    go func() {
        if err := srv.ListenAndServe(); err != nil && errors.Is(err, http.ErrServerClosed) {
            log.Printf("listen: %s\n", err)
        }
    }()

    // Wait for interrupt signal to gracefully shutdown the server with
    // a timeout of 5 seconds.
    quit := make(chan os.Signal, 1)
    // kill (no param) default send syscall.SIGTERM
    // kill -2 is syscall.SIGINT
    // kill -9 is syscall.SIGKILL but can't be catch, so don't need add it
    signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
    <-quit
    log.Println("Shutting down server...")

    // The context is used to inform the server it has 5 seconds to finish
    // the request it is currently handling
    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
    defer cancel()

    if err := srv.Shutdown(ctx); err != nil {
        log.Fatal("Server forced to shutdown:", err)
    }

    log.Println("Server exiting")
}

Expectations

$ curl -H "X-Forwarded-For: 8.8.8.8" http://localhost:8080/
Welcome Gin Server; Client IP is: 8.8.8.8

Actual result

$ curl -i -H "X-Forwarded-For: 8.8.8.8" http://localhost:8080/

HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Date: Thu, 15 Apr 2021 18:04:59 GMT
Content-Length: 37

Welcome Gin Server; Client IP is: ::1
$ curl -i -H "X-Forwarded-For: 8.8.8.8" http://127.0.0.1:8080                                                                                                                                        
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Date: Thu, 15 Apr 2021 18:09:30 GMT
Content-Length: 43

Welcome Gin Server; Client IP is: 127.0.0.1

Environment

yiranzai commented 3 years ago

Hey man https://github.com/gin-gonic/gin/pull/2692

appleboy commented 3 years ago

fixed by #2692

almas1992 commented 3 years ago

fixed by #2692

but when built-in graceful mode, won't use any functions that start with Run, so how to solve this issue?

yiranzai commented 3 years ago

@almas1992

router.TrustedProxies = []string{"127.0.0.0/8", "192.168.0.0/16", "172.16.0.0/12", "10.0.0.0/8"}

to

router.SetTrustedProxies([]string{"127.0.0.0/8", "192.168.0.0/16", "172.16.0.0/12", "10.0.0.0/8"})
// SetTrustedProxies  set Engine.TrustedProxies
func (engine *Engine) SetTrustedProxies(trustedProxies []string) error {
    engine.TrustedProxies = trustedProxies
    return engine.parseTrustedProxies()
}