@@ -1577,3 +1577,49 @@ func mustParseUrl(t *testing.T, str string) *url.URL {
15771577 }
15781578 return url
15791579}
1580+
1581+ func TestGetRemoteAddr (t * testing.T ) {
1582+ type tc struct {
1583+ name string
1584+ remoteAddr string // r.RemoteAddr
1585+ xff string // "" = header not present
1586+ want string
1587+ }
1588+
1589+ cases := []tc {
1590+ // --- No X-Forwarded-For (uses RemoteAddr) ---
1591+ {"remote IPv4 with port" , "203.0.113.9:54321" , "" , "203.0.113.9" },
1592+ {"remote hostname with port" , "example.com:80" , "" , "example.com" },
1593+ {"remote bracketed IPv6 with port" , "[2001:db8::1]:443" , "" , "2001:db8::1" },
1594+ {"remote IPv6 with zone" , "[fe80::1%lo0]:1234" , "" , "fe80::1%lo0" },
1595+ {"remote IPv4 no port (SplitHostPort error)" , "192.0.2.10" , "" , "192.0.2.10" },
1596+ {"remote bare IPv6 no port (SplitHostPort error)" , "2001:db8::2" , "" , "2001:db8::2" },
1597+ {"remote empty string" , "" , "" , "" },
1598+ {"remote malformed string" , "1.2.3.4, nonsense" , "" , "1.2.3.4, nonsense" },
1599+
1600+ // --- X-Forwarded-For present (takes first comma-delimited token) ---
1601+ {"xff single IPv4 no port" , "203.0.113.9:54321" , "198.51.100.7" , "198.51.100.7" },
1602+ {"xff single IPv4 with port" , "203.0.113.9:54321" , "198.51.100.7:8080" , "198.51.100.7" },
1603+ {"xff single hostname with port" , "203.0.113.9:54321" , "edge.example.net:8443" , "edge.example.net" },
1604+ {"xff single bracketed IPv6 with port" , "203.0.113.9:54321" , "[2001:db8::7]:9443" , "2001:db8::7" },
1605+ {"xff IPv4-mapped IPv6 with port" , "203.0.113.9:54321" , "[::ffff:192.0.2.128]:12345" , "::ffff:192.0.2.128" },
1606+ {"xff multiple entries with port" , "203.0.113.9:54321" , "198.51.100.7:8080, 10.0.0.1:80" , "198.51.100.7" },
1607+ {"xff multiple entries no port" , "203.0.113.9:54321" , "198.51.100.7, 10.0.0.1" , "198.51.100.7" },
1608+ {"xff first entry empty" , "203.0.113.9:54321" , ", 198.51.100.7" , "" },
1609+ {"xff first entry has spaces" , "203.0.113.9:54321" , " \t \r 198.51.100.7:8080 " , "198.51.100.7" },
1610+ }
1611+
1612+ for _ , tt := range cases {
1613+ t .Run (tt .name , func (t * testing.T ) {
1614+ r := & http.Request {
1615+ RemoteAddr : tt .remoteAddr ,
1616+ Header : make (http.Header ),
1617+ }
1618+ if tt .xff != "" {
1619+ r .Header .Set ("X-Forwarded-For" , tt .xff )
1620+ }
1621+ got := getRemoteAddr (r )
1622+ assert .Equal (t , tt .want , got )
1623+ })
1624+ }
1625+ }
0 commit comments