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) } }