package ipguard import ( "net" "net/http" "testing" ) func TestClientIP(t *testing.T) { t.Run("extracts host from remote addr", func(t *testing.T) { req := &http.Request{RemoteAddr: "10.1.2.3:1234"} ip := ClientIP(req) if ip == nil || ip.String() != "10.1.2.3" { t.Fatalf("unexpected ip: %v", ip) } }) t.Run("supports plain ip", func(t *testing.T) { req := &http.Request{RemoteAddr: "8.8.8.8"} ip := ClientIP(req) if ip == nil || ip.String() != "8.8.8.8" { t.Fatalf("unexpected ip: %v", ip) } }) t.Run("invalid remote addr", func(t *testing.T) { req := &http.Request{RemoteAddr: "invalid"} if ip := ClientIP(req); ip != nil { t.Fatalf("expected nil ip, got %v", ip) } }) t.Run("prefers X-Real-IP over remote addr", func(t *testing.T) { req := &http.Request{ RemoteAddr: "172.19.0.31:5000", Header: http.Header{"X-Real-Ip": []string{"178.57.67.154"}}, } ip := ClientIP(req) if ip == nil || ip.String() != "178.57.67.154" { t.Fatalf("expected real client ip, got %v", ip) } }) t.Run("falls back to remote addr when X-Real-IP absent", func(t *testing.T) { req := &http.Request{RemoteAddr: "10.0.0.1:9000"} ip := ClientIP(req) if ip == nil || ip.String() != "10.0.0.1" { t.Fatalf("expected remote addr ip, got %v", ip) } }) t.Run("falls back to remote addr when X-Real-IP invalid", func(t *testing.T) { req := &http.Request{ RemoteAddr: "10.0.0.1:9000", Header: http.Header{"X-Real-Ip": []string{"not-an-ip"}}, } ip := ClientIP(req) if ip == nil || ip.String() != "10.0.0.1" { t.Fatalf("expected fallback to remote addr, got %v", ip) } }) } func TestAllowed(t *testing.T) { clientIP := net.ParseIP("10.1.2.3") if clientIP == nil { t.Fatal("failed to parse test ip") } t.Run("allows when cidr matches", func(t *testing.T) { allowed, err := Allowed(clientIP, []string{"10.0.0.0/8"}) if err != nil { t.Fatalf("unexpected error: %v", err) } if !allowed { t.Fatal("expected allowed") } }) t.Run("denies when cidr does not match", func(t *testing.T) { allowed, err := Allowed(clientIP, []string{"192.168.0.0/16"}) if err != nil { t.Fatalf("unexpected error: %v", err) } if allowed { t.Fatal("expected denied") } }) t.Run("allows when cidr list is empty", func(t *testing.T) { allowed, err := Allowed(clientIP, nil) if err != nil { t.Fatalf("unexpected error: %v", err) } if !allowed { t.Fatal("expected allowed") } }) t.Run("invalid cidr fails", func(t *testing.T) { _, err := Allowed(clientIP, []string{"not-a-cidr"}) if err == nil { t.Fatal("expected error") } }) t.Run("nil client ip denied when cidrs configured", func(t *testing.T) { allowed, err := Allowed(nil, []string{"10.0.0.0/8"}) if err != nil { t.Fatalf("unexpected error: %v", err) } if allowed { t.Fatal("expected denied") } }) }