gitee.com/ks-custle/core-gm@v0.0.0-20230922171213-b83bdd97b62c/net/http/httpproxy/proxy_test.go (about) 1 // Copyright 2017 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package httpproxy_test 6 7 import ( 8 "bytes" 9 "errors" 10 "fmt" 11 "net/url" 12 "os" 13 "strings" 14 "testing" 15 16 "gitee.com/ks-custle/core-gm/net/http/httpproxy" 17 ) 18 19 // setHelper calls t.Helper() for Go 1.9+ (see go19_test.go) and does nothing otherwise. 20 var setHelper = func(t *testing.T) {} 21 22 type proxyForURLTest struct { 23 cfg httpproxy.Config 24 req string // URL to fetch; blank means "http://example.com" 25 want string 26 wanterr error 27 } 28 29 func (t proxyForURLTest) String() string { 30 var buf bytes.Buffer 31 space := func() { 32 if buf.Len() > 0 { 33 buf.WriteByte(' ') 34 } 35 } 36 if t.cfg.HTTPProxy != "" { 37 fmt.Fprintf(&buf, "http_proxy=%q", t.cfg.HTTPProxy) 38 } 39 if t.cfg.HTTPSProxy != "" { 40 space() 41 fmt.Fprintf(&buf, "https_proxy=%q", t.cfg.HTTPSProxy) 42 } 43 if t.cfg.NoProxy != "" { 44 space() 45 fmt.Fprintf(&buf, "no_proxy=%q", t.cfg.NoProxy) 46 } 47 req := "http://example.com" 48 if t.req != "" { 49 req = t.req 50 } 51 space() 52 fmt.Fprintf(&buf, "req=%q", req) 53 return strings.TrimSpace(buf.String()) 54 } 55 56 var proxyForURLTests = []proxyForURLTest{{ 57 cfg: httpproxy.Config{ 58 HTTPProxy: "127.0.0.1:8080", 59 }, 60 want: "http://127.0.0.1:8080", 61 }, { 62 cfg: httpproxy.Config{ 63 HTTPProxy: "cache.corp.example.com:1234", 64 }, 65 want: "http://cache.corp.example.com:1234", 66 }, { 67 cfg: httpproxy.Config{ 68 HTTPProxy: "cache.corp.example.com", 69 }, 70 want: "http://cache.corp.example.com", 71 }, { 72 cfg: httpproxy.Config{ 73 HTTPProxy: "https://cache.corp.example.com", 74 }, 75 want: "https://cache.corp.example.com", 76 }, { 77 cfg: httpproxy.Config{ 78 HTTPProxy: "http://127.0.0.1:8080", 79 }, 80 want: "http://127.0.0.1:8080", 81 }, { 82 cfg: httpproxy.Config{ 83 HTTPProxy: "https://127.0.0.1:8080", 84 }, 85 want: "https://127.0.0.1:8080", 86 }, { 87 cfg: httpproxy.Config{ 88 HTTPProxy: "socks5://127.0.0.1", 89 }, 90 want: "socks5://127.0.0.1", 91 }, { 92 // Don't use secure for http 93 cfg: httpproxy.Config{ 94 HTTPProxy: "http.proxy.tld", 95 HTTPSProxy: "secure.proxy.tld", 96 }, 97 req: "http://insecure.tld/", 98 want: "http://http.proxy.tld", 99 }, { 100 // Use secure for https. 101 cfg: httpproxy.Config{ 102 HTTPProxy: "http.proxy.tld", 103 HTTPSProxy: "secure.proxy.tld", 104 }, 105 req: "https://secure.tld/", 106 want: "http://secure.proxy.tld", 107 }, { 108 cfg: httpproxy.Config{ 109 HTTPProxy: "http.proxy.tld", 110 HTTPSProxy: "https://secure.proxy.tld", 111 }, 112 req: "https://secure.tld/", 113 want: "https://secure.proxy.tld", 114 }, { 115 cfg: httpproxy.Config{ 116 HTTPProxy: "http.proxy.tld", 117 }, 118 req: "https://secure.tld/", 119 want: "<nil>", 120 }, { 121 cfg: httpproxy.Config{ 122 HTTPProxy: "http.proxy.tld", 123 }, 124 req: "ftp://insecure.tld/", 125 want: "<nil>", 126 }, { 127 // Issue 16405: don't use HTTP_PROXY in a CGI environment, 128 // where HTTP_PROXY can be attacker-controlled. 129 cfg: httpproxy.Config{ 130 HTTPProxy: "http://10.1.2.3:8080", 131 CGI: true, 132 }, 133 want: "<nil>", 134 wanterr: errors.New("refusing to use HTTP_PROXY value in CGI environment; see golang.org/s/cgihttpproxy"), 135 }, { 136 // HTTPS proxy is still used even in CGI environment. 137 // (perhaps dubious but it's the historical behaviour). 138 cfg: httpproxy.Config{ 139 HTTPSProxy: "https://secure.proxy.tld", 140 CGI: true, 141 }, 142 req: "https://secure.tld/", 143 want: "https://secure.proxy.tld", 144 }, { 145 want: "<nil>", 146 }, { 147 cfg: httpproxy.Config{ 148 NoProxy: "example.com", 149 HTTPProxy: "proxy", 150 }, 151 req: "http://example.com/", 152 want: "<nil>", 153 }, { 154 cfg: httpproxy.Config{ 155 NoProxy: ".example.com", 156 HTTPProxy: "proxy", 157 }, 158 req: "http://example.com/", 159 want: "http://proxy", 160 }, { 161 cfg: httpproxy.Config{ 162 NoProxy: "ample.com", 163 HTTPProxy: "proxy", 164 }, 165 req: "http://example.com/", 166 want: "http://proxy", 167 }, { 168 cfg: httpproxy.Config{ 169 NoProxy: "example.com", 170 HTTPProxy: "proxy", 171 }, 172 req: "http://foo.example.com/", 173 want: "<nil>", 174 }, { 175 cfg: httpproxy.Config{ 176 NoProxy: ".foo.com", 177 HTTPProxy: "proxy", 178 }, 179 req: "http://example.com/", 180 want: "http://proxy", 181 }} 182 183 func testProxyForURL(t *testing.T, tt proxyForURLTest) { 184 setHelper(t) 185 reqURLStr := tt.req 186 if reqURLStr == "" { 187 reqURLStr = "http://example.com" 188 } 189 reqURL, err := url.Parse(reqURLStr) 190 if err != nil { 191 t.Errorf("invalid URL %q", reqURLStr) 192 return 193 } 194 cfg := tt.cfg 195 proxyForURL := cfg.ProxyFunc() 196 url, err := proxyForURL(reqURL) 197 if g, e := fmt.Sprintf("%v", err), fmt.Sprintf("%v", tt.wanterr); g != e { 198 t.Errorf("%v: got error = %q, want %q", tt, g, e) 199 return 200 } 201 if got := fmt.Sprintf("%s", url); got != tt.want { 202 t.Errorf("%v: got URL = %q, want %q", tt, url, tt.want) 203 } 204 205 // Check that changing the Config doesn't change the results 206 // of the functuon. 207 cfg = httpproxy.Config{} 208 url, err = proxyForURL(reqURL) 209 if g, e := fmt.Sprintf("%v", err), fmt.Sprintf("%v", tt.wanterr); g != e { 210 t.Errorf("(after mutating config) %v: got error = %q, want %q", tt, g, e) 211 return 212 } 213 if got := fmt.Sprintf("%s", url); got != tt.want { 214 t.Errorf("(after mutating config) %v: got URL = %q, want %q", tt, url, tt.want) 215 } 216 } 217 218 func TestProxyForURL(t *testing.T) { 219 for _, tt := range proxyForURLTests { 220 testProxyForURL(t, tt) 221 } 222 } 223 224 func TestFromEnvironment(t *testing.T) { 225 os.Setenv("HTTP_PROXY", "httpproxy") 226 os.Setenv("HTTPS_PROXY", "httpsproxy") 227 os.Setenv("NO_PROXY", "noproxy") 228 os.Setenv("REQUEST_METHOD", "") 229 got := httpproxy.FromEnvironment() 230 want := httpproxy.Config{ 231 HTTPProxy: "httpproxy", 232 HTTPSProxy: "httpsproxy", 233 NoProxy: "noproxy", 234 } 235 if *got != want { 236 t.Errorf("unexpected proxy config, got %#v want %#v", got, want) 237 } 238 } 239 240 func TestFromEnvironmentWithRequestMethod(t *testing.T) { 241 os.Setenv("HTTP_PROXY", "httpproxy") 242 os.Setenv("HTTPS_PROXY", "httpsproxy") 243 os.Setenv("NO_PROXY", "noproxy") 244 os.Setenv("REQUEST_METHOD", "PUT") 245 got := httpproxy.FromEnvironment() 246 want := httpproxy.Config{ 247 HTTPProxy: "httpproxy", 248 HTTPSProxy: "httpsproxy", 249 NoProxy: "noproxy", 250 CGI: true, 251 } 252 if *got != want { 253 t.Errorf("unexpected proxy config, got %#v want %#v", got, want) 254 } 255 } 256 257 func TestFromEnvironmentLowerCase(t *testing.T) { 258 os.Setenv("http_proxy", "httpproxy") 259 os.Setenv("https_proxy", "httpsproxy") 260 os.Setenv("no_proxy", "noproxy") 261 os.Setenv("REQUEST_METHOD", "") 262 got := httpproxy.FromEnvironment() 263 want := httpproxy.Config{ 264 HTTPProxy: "httpproxy", 265 HTTPSProxy: "httpsproxy", 266 NoProxy: "noproxy", 267 } 268 if *got != want { 269 t.Errorf("unexpected proxy config, got %#v want %#v", got, want) 270 } 271 } 272 273 var UseProxyTests = []struct { 274 host string 275 match bool 276 }{ 277 // Never proxy localhost: 278 {"localhost", false}, 279 {"127.0.0.1", false}, 280 {"127.0.0.2", false}, 281 {"[::1]", false}, 282 {"[::2]", true}, // not a loopback address 283 284 {"192.168.1.1", false}, // matches exact IPv4 285 {"192.168.1.2", true}, // ports do not match 286 {"192.168.1.3", false}, // matches exact IPv4:port 287 {"192.168.1.4", true}, // no match 288 {"10.0.0.2", false}, // matches IPv4/CIDR 289 {"[2001:db8::52:0:1]", false}, // matches exact IPv6 290 {"[2001:db8::52:0:2]", true}, // no match 291 {"[2001:db8::52:0:3]", false}, // matches exact [IPv6]:port 292 {"[2002:db8:a::123]", false}, // matches IPv6/CIDR 293 {"[fe80::424b:c8be:1643:a1b6]", true}, // no match 294 295 {"barbaz.net", true}, // does not match as .barbaz.net 296 {"www.barbaz.net", false}, // does match as .barbaz.net 297 {"foobar.com", false}, // does match as foobar.com 298 {"www.foobar.com", false}, // match because NO_PROXY includes "foobar.com" 299 {"foofoobar.com", true}, // not match as a part of foobar.com 300 {"baz.com", true}, // not match as a part of barbaz.com 301 {"localhost.net", true}, // not match as suffix of address 302 {"local.localhost", true}, // not match as prefix as address 303 {"barbarbaz.net", true}, // not match, wrong domain 304 {"wildcard.io", true}, // does not match as *.wildcard.io 305 {"nested.wildcard.io", false}, // match as *.wildcard.io 306 {"awildcard.io", true}, // not a match because of '*' 307 } 308 309 var noProxy = "foobar.com, .barbaz.net, *.wildcard.io, 192.168.1.1, 192.168.1.2:81, 192.168.1.3:80, 10.0.0.0/30, 2001:db8::52:0:1, [2001:db8::52:0:2]:443, [2001:db8::52:0:3]:80, 2002:db8:a::45/64" 310 311 func TestUseProxy(t *testing.T) { 312 cfg := &httpproxy.Config{ 313 NoProxy: noProxy, 314 } 315 for _, test := range UseProxyTests { 316 if httpproxy.ExportUseProxy(cfg, test.host+":80") != test.match { 317 t.Errorf("useProxy(%v) = %v, want %v", test.host, !test.match, test.match) 318 } 319 } 320 } 321 322 func TestInvalidNoProxy(t *testing.T) { 323 cfg := &httpproxy.Config{ 324 NoProxy: ":1", 325 } 326 ok := httpproxy.ExportUseProxy(cfg, "example.com:80") // should not panic 327 if !ok { 328 t.Errorf("useProxy unexpected return; got false; want true") 329 } 330 } 331 332 func TestAllNoProxy(t *testing.T) { 333 cfg := &httpproxy.Config{ 334 NoProxy: "*", 335 } 336 for _, test := range UseProxyTests { 337 if httpproxy.ExportUseProxy(cfg, test.host+":80") != false { 338 t.Errorf("useProxy(%v) = true, want false", test.host) 339 } 340 } 341 } 342 343 func BenchmarkProxyForURL(b *testing.B) { 344 cfg := &httpproxy.Config{ 345 HTTPProxy: "http://proxy.example.org", 346 HTTPSProxy: "https://proxy.example.org", 347 NoProxy: noProxy, 348 } 349 for _, test := range UseProxyTests { 350 u, err := url.Parse("https://" + test.host + ":80") 351 if err != nil { 352 b.Fatalf("parsed failed: %s", test.host) 353 } 354 proxyFunc := cfg.ProxyFunc() 355 b.Run(test.host, func(b *testing.B) { 356 for n := 0; n < b.N; n++ { 357 if au, e := proxyFunc(u); e != nil && test.match == (au != nil) { 358 b.Errorf("useProxy(%v) = %v, want %v", test.host, !test.match, test.match) 359 } 360 } 361 }) 362 } 363 }