OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 import "package:crypto/crypto.dart"; | 5 import "package:crypto/crypto.dart"; |
6 import "package:expect/expect.dart"; | 6 import "package:expect/expect.dart"; |
7 import "package:path/path.dart"; | 7 import "package:path/path.dart"; |
8 import "dart:async"; | 8 import "dart:async"; |
9 import "dart:io"; | 9 import "dart:io"; |
10 import 'dart:convert'; | 10 import 'dart:convert'; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
70 } | 70 } |
71 | 71 |
72 Future<Server> setupServer(int proxyHops, | 72 Future<Server> setupServer(int proxyHops, |
73 {List<String> directRequestPaths: const <String>[], | 73 {List<String> directRequestPaths: const <String>[], |
74 secure: false}) { | 74 secure: false}) { |
75 Server server = new Server(proxyHops, directRequestPaths, secure); | 75 Server server = new Server(proxyHops, directRequestPaths, secure); |
76 return server.start(); | 76 return server.start(); |
77 } | 77 } |
78 | 78 |
79 class ProxyServer { | 79 class ProxyServer { |
| 80 final bool ipV6; |
80 HttpServer server; | 81 HttpServer server; |
81 HttpClient client; | 82 HttpClient client; |
82 int requestCount = 0; | 83 int requestCount = 0; |
83 String authScheme; | 84 String authScheme; |
84 String realm = "test"; | 85 String realm = "test"; |
85 String username; | 86 String username; |
86 String password; | 87 String password; |
87 | 88 |
88 var ha1; | 89 var ha1; |
89 String serverAlgorithm = "MD5"; | 90 String serverAlgorithm = "MD5"; |
90 String serverQop = "auth"; | 91 String serverQop = "auth"; |
91 Set ncs = new Set(); | 92 Set ncs = new Set(); |
92 | 93 |
93 var nonce = "12345678"; // No need for random nonce in test. | 94 var nonce = "12345678"; // No need for random nonce in test. |
94 | 95 |
95 ProxyServer() : client = new HttpClient(); | 96 ProxyServer({this.ipV6: false}) : client = new HttpClient(); |
96 | 97 |
97 void useBasicAuthentication(String username, String password) { | 98 void useBasicAuthentication(String username, String password) { |
98 this.username = username; | 99 this.username = username; |
99 this.password = password; | 100 this.password = password; |
100 authScheme = "Basic"; | 101 authScheme = "Basic"; |
101 } | 102 } |
102 | 103 |
103 void useDigestAuthentication(String username, String password) { | 104 void useDigestAuthentication(String username, String password) { |
104 this.username = username; | 105 this.username = username; |
105 this.password = password; | 106 this.password = password; |
(...skipping 28 matching lines...) Expand all Loading... |
134 authHeader.write(', algorithm=$serverAlgorithm'); | 135 authHeader.write(', algorithm=$serverAlgorithm'); |
135 } | 136 } |
136 if (serverQop != null) authHeader.write(', qop="$serverQop"'); | 137 if (serverQop != null) authHeader.write(', qop="$serverQop"'); |
137 response.headers.set(HttpHeaders.PROXY_AUTHENTICATE, authHeader); | 138 response.headers.set(HttpHeaders.PROXY_AUTHENTICATE, authHeader); |
138 response.close(); | 139 response.close(); |
139 }); | 140 }); |
140 } | 141 } |
141 | 142 |
142 Future<ProxyServer> start() { | 143 Future<ProxyServer> start() { |
143 var x = new Completer(); | 144 var x = new Completer(); |
144 HttpServer.bind("localhost", 0).then((s) { | 145 var host = ipV6 ? "::1" : "localhost"; |
| 146 HttpServer.bind(host, 0).then((s) { |
145 server = s; | 147 server = s; |
146 x.complete(this); | 148 x.complete(this); |
147 server.listen((HttpRequest request) { | 149 server.listen((HttpRequest request) { |
148 requestCount++; | 150 requestCount++; |
149 if (username != null && password != null) { | 151 if (username != null && password != null) { |
150 if (request.headers[HttpHeaders.PROXY_AUTHORIZATION] == null) { | 152 if (request.headers[HttpHeaders.PROXY_AUTHORIZATION] == null) { |
151 if (authScheme == "Digest") { | 153 if (authScheme == "Digest") { |
152 digestAuthenticationRequired(request); | 154 digestAuthenticationRequired(request); |
153 } else { | 155 } else { |
154 basicAuthenticationRequired(request); | 156 basicAuthenticationRequired(request); |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
262 } | 264 } |
263 | 265 |
264 void shutdown() { | 266 void shutdown() { |
265 server.close(); | 267 server.close(); |
266 client.close(); | 268 client.close(); |
267 } | 269 } |
268 | 270 |
269 int get port => server.port; | 271 int get port => server.port; |
270 } | 272 } |
271 | 273 |
272 Future<ProxyServer> setupProxyServer() { | 274 Future<ProxyServer> setupProxyServer({ipV6: false}) { |
273 ProxyServer proxyServer = new ProxyServer(); | 275 ProxyServer proxyServer = new ProxyServer(ipV6: ipV6); |
274 return proxyServer.start(); | 276 return proxyServer.start(); |
275 } | 277 } |
276 | 278 |
277 testInvalidProxy() { | 279 testInvalidProxy() { |
278 HttpClient client = new HttpClient(); | 280 HttpClient client = new HttpClient(); |
279 | 281 |
280 client.findProxy = (Uri uri) => ""; | 282 client.findProxy = (Uri uri) => ""; |
281 client.getUrl(Uri.parse("http://www.google.com/test")) | 283 client.getUrl(Uri.parse("http://www.google.com/test")) |
282 .catchError((error) {}, test: (e) => e is HttpException); | 284 .catchError((error) {}, test: (e) => e is HttpException); |
283 | 285 |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
390 } | 392 } |
391 | 393 |
392 test(false); | 394 test(false); |
393 test(true); | 395 test(true); |
394 } | 396 } |
395 }); | 397 }); |
396 }); | 398 }); |
397 }); | 399 }); |
398 } | 400 } |
399 | 401 |
| 402 int testProxyIPV6DoneCount = 0; |
| 403 void testProxyIPV6() { |
| 404 setupProxyServer(ipV6: true).then((proxyServer) { |
| 405 setupServer(1, directRequestPaths: ["/4"]).then((server) { |
| 406 setupServer(1, directRequestPaths: ["/4"], secure: true).then((secureServer) { |
| 407 HttpClient client = new HttpClient(); |
| 408 |
| 409 List<String> proxy = ["PROXY [::1]:${proxyServer.port}"]; |
| 410 client.findProxy = (Uri uri) { |
| 411 // Pick the proxy configuration based on the request path. |
| 412 int index = int.parse(uri.path.substring(1)); |
| 413 return proxy[index]; |
| 414 }; |
| 415 |
| 416 for (int i = 0; i < proxy.length; i++) { |
| 417 test(bool secure) { |
| 418 String url = secure |
| 419 ? "https://localhost:${secureServer.port}/$i" |
| 420 : "http://localhost:${server.port}/$i"; |
| 421 |
| 422 client.postUrl(Uri.parse(url)) |
| 423 .then((HttpClientRequest clientRequest) { |
| 424 String content = "$i$i$i"; |
| 425 clientRequest.write(content); |
| 426 return clientRequest.close(); |
| 427 }) |
| 428 .then((HttpClientResponse response) { |
| 429 response.listen((_) {}, onDone: () { |
| 430 testProxyIPV6DoneCount++; |
| 431 if (testProxyIPV6DoneCount == proxy.length * 2) { |
| 432 Expect.equals(proxy.length, server.requestCount); |
| 433 Expect.equals(proxy.length, secureServer.requestCount); |
| 434 proxyServer.shutdown(); |
| 435 server.shutdown(); |
| 436 secureServer.shutdown(); |
| 437 client.close(); |
| 438 } |
| 439 }); |
| 440 }); |
| 441 } |
| 442 |
| 443 test(false); |
| 444 test(true); |
| 445 } |
| 446 }); |
| 447 }); |
| 448 }); |
| 449 } |
| 450 |
400 int testProxyChainDoneCount = 0; | 451 int testProxyChainDoneCount = 0; |
401 void testProxyChain() { | 452 void testProxyChain() { |
402 // Setup two proxy servers having the first using the second as its proxy. | 453 // Setup two proxy servers having the first using the second as its proxy. |
403 setupProxyServer().then((proxyServer1) { | 454 setupProxyServer().then((proxyServer1) { |
404 setupProxyServer().then((proxyServer2) { | 455 setupProxyServer().then((proxyServer2) { |
405 proxyServer1.client.findProxy = (_) => "PROXY localhost:${proxyServer2.port}"; | 456 proxyServer1.client.findProxy = (_) => "PROXY localhost:${proxyServer2.port}"; |
406 | 457 |
407 setupServer(2, directRequestPaths: ["/4"]).then((server) { | 458 setupServer(2, directRequestPaths: ["/4"]).then((server) { |
408 HttpClient client = new HttpClient(); | 459 HttpClient client = new HttpClient(); |
409 | 460 |
(...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
749 var testPkcertDatabase = Platform.script.resolve('pkcert').toFilePath(); | 800 var testPkcertDatabase = Platform.script.resolve('pkcert').toFilePath(); |
750 SecureSocket.initialize(database: testPkcertDatabase, | 801 SecureSocket.initialize(database: testPkcertDatabase, |
751 password: 'dartdart'); | 802 password: 'dartdart'); |
752 } | 803 } |
753 | 804 |
754 main() { | 805 main() { |
755 InitializeSSL(); | 806 InitializeSSL(); |
756 testInvalidProxy(); | 807 testInvalidProxy(); |
757 testDirectProxy(); | 808 testDirectProxy(); |
758 testProxy(); | 809 testProxy(); |
| 810 testProxyIPV6(); |
759 testProxyChain(); | 811 testProxyChain(); |
760 testProxyFromEnviroment(); | 812 testProxyFromEnviroment(); |
761 // The two invocations of uses the same global variable for state - | 813 // The two invocations of uses the same global variable for state - |
762 // run one after the other. | 814 // run one after the other. |
763 testProxyAuthenticate(false) | 815 testProxyAuthenticate(false) |
764 .then((_) => testProxyAuthenticate(true)); | 816 .then((_) => testProxyAuthenticate(true)); |
765 // This test is not normally run. It can be used for locally testing | 817 // This test is not normally run. It can be used for locally testing |
766 // with a real proxy server (e.g. Apache). | 818 // with a real proxy server (e.g. Apache). |
767 //testRealProxy(); | 819 //testRealProxy(); |
768 //testRealProxyAuth(); | 820 //testRealProxyAuth(); |
769 } | 821 } |
OLD | NEW |