first commit

This commit is contained in:
2026-05-13 03:05:24 +03:30
commit 4c7343665a
27 changed files with 2581 additions and 0 deletions

View File

@@ -0,0 +1,137 @@
package clientip
import (
"net/http"
"net/netip"
"testing"
)
func TestResolverUsesRemoteAddressByDefault(t *testing.T) {
req := &http.Request{
Header: http.Header{"X-Forwarded-For": {"203.0.113.10"}},
RemoteAddr: "198.51.100.20:54123",
}
got := (Resolver{}).FromRequest(req)
want := "198.51.100.20"
if got != want {
t.Fatalf("got %q, want %q", got, want)
}
}
func TestResolverCanTrustForwardedFor(t *testing.T) {
req := &http.Request{
Header: http.Header{
"X-Forwarded-For": {"203.0.113.10, 198.51.100.20"},
},
RemoteAddr: "192.0.2.30:54123",
}
got := (Resolver{TrustProxyHeaders: true}).FromRequest(req)
want := "203.0.113.10"
if got != want {
t.Fatalf("got %q, want %q", got, want)
}
}
func TestResolverCanTrustRFCForwardedHeader(t *testing.T) {
req := &http.Request{
Header: http.Header{
"Forwarded": {`for="203.0.113.10";proto=https;host=ip.example.com`},
},
RemoteAddr: "192.0.2.30:54123",
}
got := (Resolver{TrustProxyHeaders: true}).FromRequest(req)
want := "203.0.113.10"
if got != want {
t.Fatalf("got %q, want %q", got, want)
}
}
func TestResolverOnlyTrustsConfiguredProxyCIDRs(t *testing.T) {
trustedProxy := netip.MustParsePrefix("127.0.0.1/32")
resolver := Resolver{
TrustProxyHeaders: true,
TrustedProxies: []netip.Prefix{trustedProxy},
}
req := &http.Request{
Header: http.Header{"X-Forwarded-For": {"203.0.113.10"}},
RemoteAddr: "198.51.100.20:54123",
}
got := resolver.FromRequest(req)
want := "198.51.100.20"
if got != want {
t.Fatalf("got %q, want %q", got, want)
}
}
func TestResolverTrustsForwardedHeaderFromConfiguredProxyCIDR(t *testing.T) {
trustedProxy := netip.MustParsePrefix("127.0.0.1/32")
resolver := Resolver{
TrustProxyHeaders: true,
TrustedProxies: []netip.Prefix{trustedProxy},
}
req := &http.Request{
Header: http.Header{"X-Forwarded-For": {"203.0.113.10"}},
RemoteAddr: "127.0.0.1:54123",
}
got := resolver.FromRequest(req)
want := "203.0.113.10"
if got != want {
t.Fatalf("got %q, want %q", got, want)
}
}
func TestResolverFallsBackToRealIPHeader(t *testing.T) {
req := &http.Request{
Header: http.Header{"X-Real-IP": {"203.0.113.10"}},
RemoteAddr: "192.0.2.30:54123",
}
got := (Resolver{TrustProxyHeaders: true}).FromRequest(req)
want := "203.0.113.10"
if got != want {
t.Fatalf("got %q, want %q", got, want)
}
}
func TestResolverHandlesIPv6RemoteAddress(t *testing.T) {
req := &http.Request{
Header: http.Header{},
RemoteAddr: "[2001:db8::1]:54123",
}
got := (Resolver{}).FromRequest(req)
want := "2001:db8::1"
if got != want {
t.Fatalf("got %q, want %q", got, want)
}
}
func TestResolverSkipsInvalidForwardedForEntries(t *testing.T) {
req := &http.Request{
Header: http.Header{
"X-Forwarded-For": {"unknown, 203.0.113.10"},
},
RemoteAddr: "192.0.2.30:54123",
}
got := (Resolver{TrustProxyHeaders: true}).FromRequest(req)
want := "203.0.113.10"
if got != want {
t.Fatalf("got %q, want %q", got, want)
}
}