Skip to content

Latest commit

 

History

History
41 lines (34 loc) · 1.01 KB

clientip.md

File metadata and controls

41 lines (34 loc) · 1.01 KB
package main

import (
	"fmt"
	"net"
	"net/http"
	"strings"
)

// https://github.com/gin-gonic/gin/blob/4867ff9634d1889156587d5add70d2b29c447542/context.go#L636

// ClientIP implements a best effort algorithm to return the real client IP, it parses
// X-Real-IP and X-Forwarded-For in order to work properly with reverse-proxies such us: nginx or haproxy.
// Use X-Forwarded-For before X-Real-Ip as nginx uses X-Real-Ip with the proxy's IP.
func ClientIP(r *http.Request) string {
	clientIP := r.Header.Get("X-Forwarded-For")
	clientIP = strings.TrimSpace(strings.Split(clientIP, ",")[0])
	if clientIP == "" {
		clientIP = strings.TrimSpace(r.Header.Get("X-Real-Ip"))
	}
	if clientIP != "" {
		return clientIP
	}

	if ip, _, err := net.SplitHostPort(strings.TrimSpace(r.RemoteAddr)); err == nil {
		return ip
	}

	return ""
}

func main() {
	mux := http.NewServeMux()
	mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "ip is %s", ClientIP(r))
	})

	http.ListenAndServe(":8080", mux)
}