1
2
3
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 "golang.org/x/net/http/httpproxy"
17 )
18
19
20 var setHelper = func(t *testing.T) {}
21
22 type proxyForURLTest struct {
23 cfg httpproxy.Config
24 req string
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
73 cfg: httpproxy.Config{
74 HTTPProxy: "localhost",
75 },
76 want: "http://localhost",
77 }, {
78 cfg: httpproxy.Config{
79 HTTPProxy: "https://cache.corp.example.com",
80 },
81 want: "https://cache.corp.example.com",
82 }, {
83 cfg: httpproxy.Config{
84 HTTPProxy: "http://127.0.0.1:8080",
85 },
86 want: "http://127.0.0.1:8080",
87 }, {
88 cfg: httpproxy.Config{
89 HTTPProxy: "https://127.0.0.1:8080",
90 },
91 want: "https://127.0.0.1:8080",
92 }, {
93 cfg: httpproxy.Config{
94 HTTPProxy: "socks5://127.0.0.1",
95 },
96 want: "socks5://127.0.0.1",
97 }, {
98
99 cfg: httpproxy.Config{
100 HTTPProxy: "foo://host",
101 },
102 want: "foo://host",
103 }, {
104
105 cfg: httpproxy.Config{
106 HTTPProxy: "http.proxy.tld",
107 HTTPSProxy: "secure.proxy.tld",
108 },
109 req: "http://insecure.tld/",
110 want: "http://http.proxy.tld",
111 }, {
112
113 cfg: httpproxy.Config{
114 HTTPProxy: "http.proxy.tld",
115 HTTPSProxy: "secure.proxy.tld",
116 },
117 req: "https://secure.tld/",
118 want: "http://secure.proxy.tld",
119 }, {
120 cfg: httpproxy.Config{
121 HTTPProxy: "http.proxy.tld",
122 HTTPSProxy: "https://secure.proxy.tld",
123 },
124 req: "https://secure.tld/",
125 want: "https://secure.proxy.tld",
126 }, {
127 cfg: httpproxy.Config{
128 HTTPProxy: "http.proxy.tld",
129 },
130 req: "https://secure.tld/",
131 want: "<nil>",
132 }, {
133 cfg: httpproxy.Config{
134 HTTPProxy: "http.proxy.tld",
135 },
136 req: "ftp://insecure.tld/",
137 want: "<nil>",
138 }, {
139
140
141 cfg: httpproxy.Config{
142 HTTPProxy: "http://10.1.2.3:8080",
143 CGI: true,
144 },
145 want: "<nil>",
146 wanterr: errors.New("refusing to use HTTP_PROXY value in CGI environment; see golang.org/s/cgihttpproxy"),
147 }, {
148
149
150 cfg: httpproxy.Config{
151 HTTPSProxy: "https://secure.proxy.tld",
152 CGI: true,
153 },
154 req: "https://secure.tld/",
155 want: "https://secure.proxy.tld",
156 }, {
157 want: "<nil>",
158 }, {
159 cfg: httpproxy.Config{
160 NoProxy: "example.com",
161 HTTPProxy: "proxy",
162 },
163 req: "http://example.com/",
164 want: "<nil>",
165 }, {
166 cfg: httpproxy.Config{
167 NoProxy: ".example.com",
168 HTTPProxy: "proxy",
169 },
170 req: "http://example.com/",
171 want: "http://proxy",
172 }, {
173 cfg: httpproxy.Config{
174 NoProxy: "ample.com",
175 HTTPProxy: "proxy",
176 },
177 req: "http://example.com/",
178 want: "http://proxy",
179 }, {
180 cfg: httpproxy.Config{
181 NoProxy: "example.com",
182 HTTPProxy: "proxy",
183 },
184 req: "http://foo.example.com/",
185 want: "<nil>",
186 }, {
187 cfg: httpproxy.Config{
188 NoProxy: ".foo.com",
189 HTTPProxy: "proxy",
190 },
191 req: "http://example.com/",
192 want: "http://proxy",
193 }, {
194 cfg: httpproxy.Config{
195 NoProxy: ".示例.com",
196 HTTPProxy: "proxy",
197 },
198 req: "http://www.示例.com",
199 want: "<nil>",
200 }, {
201 cfg: httpproxy.Config{
202 NoProxy: "xn--fsq092h.com",
203 HTTPProxy: "proxy",
204 },
205 req: "http://www.示例.com",
206 want: "<nil>",
207 }, {
208 cfg: httpproxy.Config{
209 NoProxy: "示例.com",
210 HTTPProxy: "proxy",
211 },
212 req: "http://www.xn--fsq092h.com",
213 want: "<nil>",
214 },
215 }
216
217 func testProxyForURL(t *testing.T, tt proxyForURLTest) {
218 setHelper(t)
219 reqURLStr := tt.req
220 if reqURLStr == "" {
221 reqURLStr = "http://example.com"
222 }
223 reqURL, err := url.Parse(reqURLStr)
224 if err != nil {
225 t.Errorf("invalid URL %q", reqURLStr)
226 return
227 }
228 cfg := tt.cfg
229 proxyForURL := cfg.ProxyFunc()
230 url, err := proxyForURL(reqURL)
231 if g, e := fmt.Sprintf("%v", err), fmt.Sprintf("%v", tt.wanterr); g != e {
232 t.Errorf("%v: got error = %q, want %q", tt, g, e)
233 return
234 }
235 if got := fmt.Sprintf("%s", url); got != tt.want {
236 t.Errorf("%v: got URL = %q, want %q", tt, url, tt.want)
237 }
238
239
240
241 cfg = httpproxy.Config{}
242 url, err = proxyForURL(reqURL)
243 if g, e := fmt.Sprintf("%v", err), fmt.Sprintf("%v", tt.wanterr); g != e {
244 t.Errorf("(after mutating config) %v: got error = %q, want %q", tt, g, e)
245 return
246 }
247 if got := fmt.Sprintf("%s", url); got != tt.want {
248 t.Errorf("(after mutating config) %v: got URL = %q, want %q", tt, url, tt.want)
249 }
250 }
251
252 func TestProxyForURL(t *testing.T) {
253 for _, tt := range proxyForURLTests {
254 testProxyForURL(t, tt)
255 }
256 }
257
258 func TestFromEnvironment(t *testing.T) {
259 os.Setenv("HTTP_PROXY", "httpproxy")
260 os.Setenv("HTTPS_PROXY", "httpsproxy")
261 os.Setenv("NO_PROXY", "noproxy")
262 os.Setenv("REQUEST_METHOD", "")
263 got := httpproxy.FromEnvironment()
264 want := httpproxy.Config{
265 HTTPProxy: "httpproxy",
266 HTTPSProxy: "httpsproxy",
267 NoProxy: "noproxy",
268 }
269 if *got != want {
270 t.Errorf("unexpected proxy config, got %#v want %#v", got, want)
271 }
272 }
273
274 func TestFromEnvironmentWithRequestMethod(t *testing.T) {
275 os.Setenv("HTTP_PROXY", "httpproxy")
276 os.Setenv("HTTPS_PROXY", "httpsproxy")
277 os.Setenv("NO_PROXY", "noproxy")
278 os.Setenv("REQUEST_METHOD", "PUT")
279 got := httpproxy.FromEnvironment()
280 want := httpproxy.Config{
281 HTTPProxy: "httpproxy",
282 HTTPSProxy: "httpsproxy",
283 NoProxy: "noproxy",
284 CGI: true,
285 }
286 if *got != want {
287 t.Errorf("unexpected proxy config, got %#v want %#v", got, want)
288 }
289 }
290
291 func TestFromEnvironmentLowerCase(t *testing.T) {
292 os.Setenv("http_proxy", "httpproxy")
293 os.Setenv("https_proxy", "httpsproxy")
294 os.Setenv("no_proxy", "noproxy")
295 os.Setenv("REQUEST_METHOD", "")
296 got := httpproxy.FromEnvironment()
297 want := httpproxy.Config{
298 HTTPProxy: "httpproxy",
299 HTTPSProxy: "httpsproxy",
300 NoProxy: "noproxy",
301 }
302 if *got != want {
303 t.Errorf("unexpected proxy config, got %#v want %#v", got, want)
304 }
305 }
306
307 var UseProxyTests = []struct {
308 host string
309 match bool
310 }{
311
312 {"localhost", false},
313 {"127.0.0.1", false},
314 {"127.0.0.2", false},
315 {"[::1]", false},
316 {"[::2]", true},
317
318 {"192.168.1.1", false},
319 {"192.168.1.2", true},
320 {"192.168.1.3", false},
321 {"192.168.1.4", true},
322 {"10.0.0.2", false},
323 {"[2001:db8::52:0:1]", false},
324 {"[2001:db8::52:0:2]", true},
325 {"[2001:db8::52:0:3]", false},
326 {"[2002:db8:a::123]", false},
327 {"[fe80::424b:c8be:1643:a1b6]", true},
328
329 {"barbaz.net", true},
330 {"www.barbaz.net", false},
331 {"foobar.com", false},
332 {"www.foobar.com", false},
333 {"foofoobar.com", true},
334 {"baz.com", true},
335 {"localhost.net", true},
336 {"local.localhost", true},
337 {"barbarbaz.net", true},
338 {"wildcard.io", true},
339 {"nested.wildcard.io", false},
340 {"awildcard.io", true},
341 }
342
343 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"
344
345 func TestUseProxy(t *testing.T) {
346 cfg := &httpproxy.Config{
347 NoProxy: noProxy,
348 }
349 for _, test := range UseProxyTests {
350 if httpproxy.ExportUseProxy(cfg, test.host+":80") != test.match {
351 t.Errorf("useProxy(%v) = %v, want %v", test.host, !test.match, test.match)
352 }
353 }
354 }
355
356 func TestInvalidNoProxy(t *testing.T) {
357 cfg := &httpproxy.Config{
358 NoProxy: ":1",
359 }
360 ok := httpproxy.ExportUseProxy(cfg, "example.com:80")
361 if !ok {
362 t.Errorf("useProxy unexpected return; got false; want true")
363 }
364 }
365
366 func TestAllNoProxy(t *testing.T) {
367 cfg := &httpproxy.Config{
368 NoProxy: "*",
369 }
370 for _, test := range UseProxyTests {
371 if httpproxy.ExportUseProxy(cfg, test.host+":80") != false {
372 t.Errorf("useProxy(%v) = true, want false", test.host)
373 }
374 }
375 }
376
377 func BenchmarkProxyForURL(b *testing.B) {
378 cfg := &httpproxy.Config{
379 HTTPProxy: "http://proxy.example.org",
380 HTTPSProxy: "https://proxy.example.org",
381 NoProxy: noProxy,
382 }
383 for _, test := range UseProxyTests {
384 u, err := url.Parse("https://" + test.host + ":80")
385 if err != nil {
386 b.Fatalf("parsed failed: %s", test.host)
387 }
388 proxyFunc := cfg.ProxyFunc()
389 b.Run(test.host, func(b *testing.B) {
390 for n := 0; n < b.N; n++ {
391 if au, e := proxyFunc(u); e != nil && test.match == (au != nil) {
392 b.Errorf("useProxy(%v) = %v, want %v", test.host, !test.match, test.match)
393 }
394 }
395 })
396 }
397 }
398
View as plain text