feat(log): 多源 clientIP 降级与去重 ip_chain
按 EO→XFF非回环→X-Real→RemoteAddr 选取 ip;访问日志附带去重 ip_chain;登录限流改用 clientIP。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
package hotime
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestResolveClientIP_EOPreferred(t *testing.T) {
|
||||
req, _ := http.NewRequest("GET", "/", nil)
|
||||
req.Header.Set("EO-Connecting-IP", "171.1.2.3")
|
||||
req.Header.Set("X-Real-IP", "43.1.2.3")
|
||||
req.Header.Set("X-Forwarded-For", "171.1.2.3, 43.1.2.3")
|
||||
req.RemoteAddr = "127.0.0.1:12345"
|
||||
|
||||
ip, chain := resolveClientIP(req)
|
||||
if ip != "171.1.2.3" {
|
||||
t.Fatalf("ip=%q want 171.1.2.3", ip)
|
||||
}
|
||||
// 去重:171 只出现一次
|
||||
if chain != "171.1.2.3,43.1.2.3,127.0.0.1" {
|
||||
t.Fatalf("chain=%q", chain)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveClientIP_SkipLoopbackXReal(t *testing.T) {
|
||||
req, _ := http.NewRequest("GET", "/", nil)
|
||||
req.Header.Set("X-Real-IP", "127.0.0.1")
|
||||
req.Header.Set("X-Forwarded-For", "171.1.2.3, 43.1.2.3")
|
||||
req.RemoteAddr = "127.0.0.1:8080"
|
||||
|
||||
ip, chain := resolveClientIP(req)
|
||||
if ip != "171.1.2.3" {
|
||||
t.Fatalf("ip=%q want 171.1.2.3", ip)
|
||||
}
|
||||
if chain != "127.0.0.1,171.1.2.3,43.1.2.3" {
|
||||
t.Fatalf("chain=%q", chain)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveClientIP_XFFBeforeMisconfiguredXReal(t *testing.T) {
|
||||
// 线上常见:X-Real-IP=CDN,XFF=客户端,CDN
|
||||
req, _ := http.NewRequest("GET", "/", nil)
|
||||
req.Header.Set("X-Real-IP", "43.1.2.3")
|
||||
req.Header.Set("X-Forwarded-For", "171.1.2.3, 43.1.2.3")
|
||||
req.RemoteAddr = "127.0.0.1:8080"
|
||||
|
||||
ip, chain := resolveClientIP(req)
|
||||
if ip != "171.1.2.3" {
|
||||
t.Fatalf("ip=%q want 171.1.2.3", ip)
|
||||
}
|
||||
if chain != "43.1.2.3,171.1.2.3,127.0.0.1" {
|
||||
t.Fatalf("chain=%q", chain)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveClientIP_XRealWhenNoXFF(t *testing.T) {
|
||||
req, _ := http.NewRequest("GET", "/", nil)
|
||||
req.Header.Set("X-Real-IP", "203.0.113.9")
|
||||
req.RemoteAddr = "10.0.0.1:80"
|
||||
|
||||
ip, chain := resolveClientIP(req)
|
||||
if ip != "203.0.113.9" {
|
||||
t.Fatalf("ip=%q want 203.0.113.9", ip)
|
||||
}
|
||||
if chain != "203.0.113.9,10.0.0.1" {
|
||||
t.Fatalf("chain=%q", chain)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveClientIP_DirectRemoteAddr(t *testing.T) {
|
||||
req, _ := http.NewRequest("GET", "/", nil)
|
||||
req.RemoteAddr = "192.168.1.8:5555"
|
||||
|
||||
ip, chain := resolveClientIP(req)
|
||||
if ip != "192.168.1.8" {
|
||||
t.Fatalf("ip=%q want 192.168.1.8", ip)
|
||||
}
|
||||
if chain != "192.168.1.8" {
|
||||
t.Fatalf("chain=%q", chain)
|
||||
}
|
||||
if clientIP(req) != ip {
|
||||
t.Fatalf("clientIP mismatch")
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveClientIP_NilReq(t *testing.T) {
|
||||
ip, chain := resolveClientIP(nil)
|
||||
if ip != "" || chain != "" {
|
||||
t.Fatalf("want empty, got %q %q", ip, chain)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user