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 // OtherResources=certificates/server_chain.pem | 5 // OtherResources=certificates/server_chain.pem |
6 // OtherResources=certificates/server_key.pem | 6 // OtherResources=certificates/server_key.pem |
7 // OtherResources=certificates/trusted_certs.pem | 7 // OtherResources=certificates/trusted_certs.pem |
8 | 8 |
9 import "package:convert/convert.dart"; | 9 import "package:convert/convert.dart"; |
10 import "package:crypto/crypto.dart"; | 10 import "package:crypto/crypto.dart"; |
11 import "package:expect/expect.dart"; | 11 import "package:expect/expect.dart"; |
12 import "dart:async"; | 12 import "dart:async"; |
13 import "dart:io"; | 13 import "dart:io"; |
14 import 'dart:convert'; | 14 import 'dart:convert'; |
15 | 15 |
16 String localFile(path) => Platform.script.resolve(path).toFilePath(); | 16 String localFile(path) => Platform.script.resolve(path).toFilePath(); |
17 | 17 |
18 SecurityContext serverContext = new SecurityContext() | 18 SecurityContext serverContext = new SecurityContext() |
19 ..useCertificateChain(localFile('certificates/server_chain.pem')) | 19 ..useCertificateChain(localFile('certificates/server_chain.pem')) |
20 ..usePrivateKey(localFile('certificates/server_key.pem'), | 20 ..usePrivateKey(localFile('certificates/server_key.pem'), |
21 password: 'dartdart'); | 21 password: 'dartdart'); |
22 | 22 |
23 SecurityContext clientContext = new SecurityContext() | 23 SecurityContext clientContext = new SecurityContext() |
24 ..setTrustedCertificates(localFile('certificates/trusted_certs.pem')); | 24 ..setTrustedCertificates(localFile('certificates/trusted_certs.pem')); |
25 | 25 |
26 class Server { | 26 class Server { |
27 HttpServer server; | 27 HttpServer server; |
28 bool secure; | 28 bool secure; |
29 int proxyHops; | 29 int proxyHops; |
30 List<String> directRequestPaths; | 30 List<String> directRequestPaths; |
31 int requestCount = 0; | 31 int requestCount = 0; |
32 | 32 |
33 Server(this.proxyHops, this.directRequestPaths, this.secure); | 33 Server(this.proxyHops, this.directRequestPaths, this.secure); |
34 | 34 |
35 Future<Server> start() { | 35 Future<Server> start() { |
36 return (secure ? | 36 return (secure |
37 HttpServer.bindSecure("localhost", 0, serverContext) : | 37 ? HttpServer.bindSecure("localhost", 0, serverContext) |
38 HttpServer.bind("localhost", 0)) | 38 : HttpServer.bind("localhost", 0)).then((s) { |
39 .then((s) { | |
40 server = s; | 39 server = s; |
41 server.listen(requestHandler); | 40 server.listen(requestHandler); |
42 return this; | 41 return this; |
43 }); | 42 }); |
44 } | 43 } |
45 | 44 |
46 void requestHandler(HttpRequest request) { | 45 void requestHandler(HttpRequest request) { |
47 var response = request.response; | 46 var response = request.response; |
48 requestCount++; | 47 requestCount++; |
49 // Check whether a proxy or direct connection is expected. | 48 // Check whether a proxy or direct connection is expected. |
50 bool direct = directRequestPaths.fold( | 49 bool direct = directRequestPaths.fold( |
51 false, | 50 false, (prev, path) => prev ? prev : path == request.uri.path); |
52 (prev, path) => prev ? prev : path == request.uri.path); | |
53 if (!secure && !direct && proxyHops > 0) { | 51 if (!secure && !direct && proxyHops > 0) { |
54 Expect.isNotNull(request.headers[HttpHeaders.VIA]); | 52 Expect.isNotNull(request.headers[HttpHeaders.VIA]); |
55 Expect.equals(1, request.headers[HttpHeaders.VIA].length); | 53 Expect.equals(1, request.headers[HttpHeaders.VIA].length); |
56 Expect.equals( | 54 Expect.equals( |
57 proxyHops, | 55 proxyHops, request.headers[HttpHeaders.VIA][0].split(",").length); |
58 request.headers[HttpHeaders.VIA][0].split(",").length); | |
59 } else { | 56 } else { |
60 Expect.isNull(request.headers[HttpHeaders.VIA]); | 57 Expect.isNull(request.headers[HttpHeaders.VIA]); |
61 } | 58 } |
62 var body = new StringBuffer(); | 59 var body = new StringBuffer(); |
63 onRequestComplete() { | 60 onRequestComplete() { |
64 String path = request.uri.path.substring(1); | 61 String path = request.uri.path.substring(1); |
65 if (path != "A") { | 62 if (path != "A") { |
66 String content = "$path$path$path"; | 63 String content = "$path$path$path"; |
67 Expect.equals(content, body.toString()); | 64 Expect.equals(content, body.toString()); |
68 } | 65 } |
69 response.write(request.uri.path); | 66 response.write(request.uri.path); |
70 response.close(); | 67 response.close(); |
71 } | 68 } |
| 69 |
72 request.listen((data) { | 70 request.listen((data) { |
73 body.write(new String.fromCharCodes(data)); | 71 body.write(new String.fromCharCodes(data)); |
74 }, onDone: onRequestComplete); | 72 }, onDone: onRequestComplete); |
75 } | 73 } |
76 | 74 |
77 void shutdown() { | 75 void shutdown() { |
78 server.close(); | 76 server.close(); |
79 } | 77 } |
80 | 78 |
81 int get port => server.port; | 79 int get port => server.port; |
82 } | 80 } |
83 | 81 |
84 Future<Server> setupServer(int proxyHops, | 82 Future<Server> setupServer(int proxyHops, |
85 {List<String> directRequestPaths: const <String>[], | 83 {List<String> directRequestPaths: const <String>[], secure: false}) { |
86 secure: false}) { | |
87 Server server = new Server(proxyHops, directRequestPaths, secure); | 84 Server server = new Server(proxyHops, directRequestPaths, secure); |
88 return server.start(); | 85 return server.start(); |
89 } | 86 } |
90 | 87 |
91 class ProxyServer { | 88 class ProxyServer { |
92 final bool ipV6; | 89 final bool ipV6; |
93 HttpServer server; | 90 HttpServer server; |
94 HttpClient client; | 91 HttpClient client; |
95 int requestCount = 0; | 92 int requestCount = 0; |
96 String authScheme; | 93 String authScheme; |
97 String realm = "test"; | 94 String realm = "test"; |
98 String username; | 95 String username; |
99 String password; | 96 String password; |
100 | 97 |
101 var ha1; | 98 var ha1; |
102 String serverAlgorithm = "MD5"; | 99 String serverAlgorithm = "MD5"; |
103 String serverQop = "auth"; | 100 String serverQop = "auth"; |
104 Set ncs = new Set(); | 101 Set ncs = new Set(); |
105 | 102 |
106 var nonce = "12345678"; // No need for random nonce in test. | 103 var nonce = "12345678"; // No need for random nonce in test. |
107 | 104 |
108 ProxyServer({this.ipV6: false}) : client = new HttpClient(); | 105 ProxyServer({this.ipV6: false}) : client = new HttpClient(); |
109 | 106 |
110 void useBasicAuthentication(String username, String password) { | 107 void useBasicAuthentication(String username, String password) { |
111 this.username = username; | 108 this.username = username; |
112 this.password = password; | 109 this.password = password; |
113 authScheme = "Basic"; | 110 authScheme = "Basic"; |
114 } | 111 } |
115 | 112 |
116 basicAuthenticationRequired(request) { | 113 basicAuthenticationRequired(request) { |
117 request.fold(null, (x, y) {}).then((_) { | 114 request.fold(null, (x, y) {}).then((_) { |
118 var response = request.response; | 115 var response = request.response; |
119 response.headers.set(HttpHeaders.PROXY_AUTHENTICATE, | 116 response.headers |
120 "Basic, realm=$realm"); | 117 .set(HttpHeaders.PROXY_AUTHENTICATE, "Basic, realm=$realm"); |
121 response.statusCode = HttpStatus.PROXY_AUTHENTICATION_REQUIRED; | 118 response.statusCode = HttpStatus.PROXY_AUTHENTICATION_REQUIRED; |
122 response.close(); | 119 response.close(); |
123 }); | 120 }); |
124 } | 121 } |
125 | 122 |
126 digestAuthenticationRequired(request, {stale: false}) { | 123 digestAuthenticationRequired(request, {stale: false}) { |
127 request.fold(null, (x, y) {}).then((_) { | 124 request.fold(null, (x, y) {}).then((_) { |
128 var response = request.response; | 125 var response = request.response; |
129 response.statusCode = HttpStatus.PROXY_AUTHENTICATION_REQUIRED; | 126 response.statusCode = HttpStatus.PROXY_AUTHENTICATION_REQUIRED; |
130 StringBuffer authHeader = new StringBuffer(); | 127 StringBuffer authHeader = new StringBuffer(); |
(...skipping 23 matching lines...) Expand all Loading... |
154 if (authScheme == "Digest") { | 151 if (authScheme == "Digest") { |
155 digestAuthenticationRequired(request); | 152 digestAuthenticationRequired(request); |
156 } else { | 153 } else { |
157 basicAuthenticationRequired(request); | 154 basicAuthenticationRequired(request); |
158 } | 155 } |
159 return; | 156 return; |
160 } else { | 157 } else { |
161 Expect.equals( | 158 Expect.equals( |
162 1, request.headers[HttpHeaders.PROXY_AUTHORIZATION].length); | 159 1, request.headers[HttpHeaders.PROXY_AUTHORIZATION].length); |
163 String authorization = | 160 String authorization = |
164 request.headers[HttpHeaders.PROXY_AUTHORIZATION][0]; | 161 request.headers[HttpHeaders.PROXY_AUTHORIZATION][0]; |
165 if (authScheme == "Basic") { | 162 if (authScheme == "Basic") { |
166 List<String> tokens = authorization.split(" "); | 163 List<String> tokens = authorization.split(" "); |
167 Expect.equals("Basic", tokens[0]); | 164 Expect.equals("Basic", tokens[0]); |
168 String auth = | 165 String auth = BASE64.encode(UTF8.encode("$username:$password")); |
169 BASE64.encode(UTF8.encode("$username:$password")); | |
170 if (auth != tokens[1]) { | 166 if (auth != tokens[1]) { |
171 basicAuthenticationRequired(request); | 167 basicAuthenticationRequired(request); |
172 return; | 168 return; |
173 } | 169 } |
174 } else { | 170 } else { |
175 HeaderValue header = | 171 HeaderValue header = |
176 HeaderValue.parse( | 172 HeaderValue.parse(authorization, parameterSeparator: ","); |
177 authorization, parameterSeparator: ","); | |
178 Expect.equals("Digest", header.value); | 173 Expect.equals("Digest", header.value); |
179 var uri = header.parameters["uri"]; | 174 var uri = header.parameters["uri"]; |
180 var qop = header.parameters["qop"]; | 175 var qop = header.parameters["qop"]; |
181 var cnonce = header.parameters["cnonce"]; | 176 var cnonce = header.parameters["cnonce"]; |
182 var nc = header.parameters["nc"]; | 177 var nc = header.parameters["nc"]; |
183 Expect.equals(username, header.parameters["username"]); | 178 Expect.equals(username, header.parameters["username"]); |
184 Expect.equals(realm, header.parameters["realm"]); | 179 Expect.equals(realm, header.parameters["realm"]); |
185 Expect.equals("MD5", header.parameters["algorithm"]); | 180 Expect.equals("MD5", header.parameters["algorithm"]); |
186 Expect.equals(nonce, header.parameters["nonce"]); | 181 Expect.equals(nonce, header.parameters["nonce"]); |
187 Expect.equals(request.uri.toString(), uri); | 182 Expect.equals(request.uri.toString(), uri); |
(...skipping 13 matching lines...) Expand all Loading... |
201 | 196 |
202 var digest = md5.convert("${request.method}:${uri}".codeUnits); | 197 var digest = md5.convert("${request.method}:${uri}".codeUnits); |
203 var ha2 = hex.encode(digest.bytes); | 198 var ha2 = hex.encode(digest.bytes); |
204 | 199 |
205 if (qop == null || qop == "" || qop == "none") { | 200 if (qop == null || qop == "" || qop == "none") { |
206 digest = md5.convert("$ha1:${nonce}:$ha2".codeUnits); | 201 digest = md5.convert("$ha1:${nonce}:$ha2".codeUnits); |
207 } else { | 202 } else { |
208 digest = md5.convert( | 203 digest = md5.convert( |
209 "$ha1:${nonce}:${nc}:${cnonce}:${qop}:$ha2".codeUnits); | 204 "$ha1:${nonce}:${nc}:${cnonce}:${qop}:$ha2".codeUnits); |
210 } | 205 } |
211 Expect.equals(hex.encode(digest.bytes), | 206 Expect.equals( |
212 header.parameters["response"]); | 207 hex.encode(digest.bytes), header.parameters["response"]); |
213 | 208 |
214 // Add a bogus Proxy-Authentication-Info for testing. | 209 // Add a bogus Proxy-Authentication-Info for testing. |
215 var info = 'rspauth="77180d1ab3d6c9de084766977790f482", ' | 210 var info = 'rspauth="77180d1ab3d6c9de084766977790f482", ' |
216 'cnonce="8f971178", ' | 211 'cnonce="8f971178", ' |
217 'nc=000002c74, ' | 212 'nc=000002c74, ' |
218 'qop=auth'; | 213 'qop=auth'; |
219 request.response.headers.set("Proxy-Authentication-Info", info); | 214 request.response.headers.set("Proxy-Authentication-Info", info); |
220 } | 215 } |
221 } | 216 } |
222 } | 217 } |
223 // Open the connection from the proxy. | 218 // Open the connection from the proxy. |
224 if (request.method == "CONNECT") { | 219 if (request.method == "CONNECT") { |
225 var tmp = request.uri.toString().split(":"); | 220 var tmp = request.uri.toString().split(":"); |
226 Socket.connect(tmp[0], int.parse(tmp[1])) | 221 Socket.connect(tmp[0], int.parse(tmp[1])).then((socket) { |
227 .then((socket) { | 222 request.response.reasonPhrase = "Connection established"; |
228 request.response.reasonPhrase = "Connection established"; | 223 request.response.detachSocket().then((detached) { |
229 request.response.detachSocket() | 224 socket.pipe(detached); |
230 .then((detached) { | 225 detached.pipe(socket); |
231 socket.pipe(detached); | 226 }); |
232 detached.pipe(socket); | 227 }); |
233 }); | 228 } else { |
| 229 client |
| 230 .openUrl(request.method, request.uri) |
| 231 .then((HttpClientRequest clientRequest) { |
| 232 // Forward all headers. |
| 233 request.headers.forEach((String name, List<String> values) { |
| 234 values.forEach((String value) { |
| 235 if (name != "content-length" && name != "via") { |
| 236 clientRequest.headers.add(name, value); |
| 237 } |
234 }); | 238 }); |
235 } else { | |
236 client.openUrl(request.method, request.uri) | |
237 .then((HttpClientRequest clientRequest) { | |
238 // Forward all headers. | |
239 request.headers.forEach((String name, List<String> values) { | |
240 values.forEach((String value) { | |
241 if (name != "content-length" && name != "via") { | |
242 clientRequest.headers.add(name, value); | |
243 } | |
244 }); | |
245 }); | |
246 // Special handling of Content-Length and Via. | |
247 clientRequest.contentLength = request.contentLength; | |
248 List<String> via = request.headers[HttpHeaders.VIA]; | |
249 String viaPrefix = via == null ? "" : "${via[0]}, "; | |
250 clientRequest.headers.add( | |
251 HttpHeaders.VIA, "${viaPrefix}1.1 localhost:$port"); | |
252 // Copy all content. | |
253 return request.pipe(clientRequest); | |
254 }) | |
255 .then((HttpClientResponse clientResponse) { | |
256 clientResponse.pipe(request.response); | |
257 }); | 239 }); |
| 240 // Special handling of Content-Length and Via. |
| 241 clientRequest.contentLength = request.contentLength; |
| 242 List<String> via = request.headers[HttpHeaders.VIA]; |
| 243 String viaPrefix = via == null ? "" : "${via[0]}, "; |
| 244 clientRequest.headers |
| 245 .add(HttpHeaders.VIA, "${viaPrefix}1.1 localhost:$port"); |
| 246 // Copy all content. |
| 247 return request.pipe(clientRequest); |
| 248 }).then((HttpClientResponse clientResponse) { |
| 249 clientResponse.pipe(request.response); |
| 250 }); |
258 } | 251 } |
259 }); | 252 }); |
260 }); | 253 }); |
261 return x.future; | 254 return x.future; |
262 } | 255 } |
263 | 256 |
264 void shutdown() { | 257 void shutdown() { |
265 server.close(); | 258 server.close(); |
266 client.close(); | 259 client.close(); |
267 } | 260 } |
268 | 261 |
269 int get port => server.port; | 262 int get port => server.port; |
270 } | 263 } |
271 | 264 |
272 Future<ProxyServer> setupProxyServer({ipV6: false}) { | 265 Future<ProxyServer> setupProxyServer({ipV6: false}) { |
273 ProxyServer proxyServer = new ProxyServer(ipV6: ipV6); | 266 ProxyServer proxyServer = new ProxyServer(ipV6: ipV6); |
274 return proxyServer.start(); | 267 return proxyServer.start(); |
275 } | 268 } |
276 | 269 |
277 testInvalidProxy() { | 270 testInvalidProxy() { |
278 HttpClient client = new HttpClient(context: clientContext); | 271 HttpClient client = new HttpClient(context: clientContext); |
279 | 272 |
280 client.findProxy = (Uri uri) => ""; | 273 client.findProxy = (Uri uri) => ""; |
281 client.getUrl(Uri.parse("http://www.google.com/test")) | 274 client |
282 .catchError((error) {}, test: (e) => e is HttpException); | 275 .getUrl(Uri.parse("http://www.google.com/test")) |
| 276 .catchError((error) {}, test: (e) => e is HttpException); |
283 | 277 |
284 client.findProxy = (Uri uri) => "XXX"; | 278 client.findProxy = (Uri uri) => "XXX"; |
285 client.getUrl(Uri.parse("http://www.google.com/test")) | 279 client |
286 .catchError((error) {}, test: (e) => e is HttpException); | 280 .getUrl(Uri.parse("http://www.google.com/test")) |
| 281 .catchError((error) {}, test: (e) => e is HttpException); |
287 | 282 |
288 client.findProxy = (Uri uri) => "PROXY www.google.com"; | 283 client.findProxy = (Uri uri) => "PROXY www.google.com"; |
289 client.getUrl(Uri.parse("http://www.google.com/test")) | 284 client |
290 .catchError((error) {}, test: (e) => e is HttpException); | 285 .getUrl(Uri.parse("http://www.google.com/test")) |
| 286 .catchError((error) {}, test: (e) => e is HttpException); |
291 | 287 |
292 client.findProxy = (Uri uri) => "PROXY www.google.com:http"; | 288 client.findProxy = (Uri uri) => "PROXY www.google.com:http"; |
293 client.getUrl(Uri.parse("http://www.google.com/test")) | 289 client |
294 .catchError((error) {}, test: (e) => e is HttpException); | 290 .getUrl(Uri.parse("http://www.google.com/test")) |
| 291 .catchError((error) {}, test: (e) => e is HttpException); |
295 } | 292 } |
296 | 293 |
297 int testDirectDoneCount = 0; | 294 int testDirectDoneCount = 0; |
298 void testDirectProxy() { | 295 void testDirectProxy() { |
299 setupServer(0).then((server) { | 296 setupServer(0).then((server) { |
300 HttpClient client = new HttpClient(context: clientContext); | 297 HttpClient client = new HttpClient(context: clientContext); |
301 List<String> proxy = | 298 List<String> proxy = [ |
302 ["DIRECT", " DIRECT ", "DIRECT ;", " DIRECT ; ", | 299 "DIRECT", |
303 ";DIRECT", " ; DIRECT ", ";;DIRECT;;"]; | 300 " DIRECT ", |
| 301 "DIRECT ;", |
| 302 " DIRECT ; ", |
| 303 ";DIRECT", |
| 304 " ; DIRECT ", |
| 305 ";;DIRECT;;" |
| 306 ]; |
304 | 307 |
305 client.findProxy = (Uri uri) { | 308 client.findProxy = (Uri uri) { |
306 int index = int.parse(uri.path.substring(1)); | 309 int index = int.parse(uri.path.substring(1)); |
307 return proxy[index]; | 310 return proxy[index]; |
308 }; | 311 }; |
309 | 312 |
310 for (int i = 0; i < proxy.length; i++) { | 313 for (int i = 0; i < proxy.length; i++) { |
311 client.getUrl(Uri.parse("http://localhost:${server.port}/$i")) | 314 client |
312 .then((HttpClientRequest clientRequest) { | 315 .getUrl(Uri.parse("http://localhost:${server.port}/$i")) |
313 String content = "$i$i$i"; | 316 .then((HttpClientRequest clientRequest) { |
314 clientRequest.contentLength = content.length; | 317 String content = "$i$i$i"; |
315 clientRequest.write(content); | 318 clientRequest.contentLength = content.length; |
316 return clientRequest.close(); | 319 clientRequest.write(content); |
317 }) | 320 return clientRequest.close(); |
318 .then((HttpClientResponse response) { | 321 }).then((HttpClientResponse response) { |
319 response.listen((_) {}, onDone: () { | 322 response.listen((_) {}, onDone: () { |
320 testDirectDoneCount++; | 323 testDirectDoneCount++; |
321 if (testDirectDoneCount == proxy.length) { | 324 if (testDirectDoneCount == proxy.length) { |
322 Expect.equals(proxy.length, server.requestCount); | 325 Expect.equals(proxy.length, server.requestCount); |
323 server.shutdown(); | 326 server.shutdown(); |
324 client.close(); | 327 client.close(); |
325 } | 328 } |
326 }); | |
327 }); | 329 }); |
| 330 }); |
328 } | 331 } |
329 }); | 332 }); |
330 } | 333 } |
331 | 334 |
332 int testProxyDoneCount = 0; | 335 int testProxyDoneCount = 0; |
333 void testProxy() { | 336 void testProxy() { |
334 setupProxyServer().then((proxyServer) { | 337 setupProxyServer().then((proxyServer) { |
335 setupServer(1, directRequestPaths: ["/4"]).then((server) { | 338 setupServer(1, directRequestPaths: ["/4"]).then((server) { |
336 setupServer(1, directRequestPaths: ["/4"], secure: true).then((secureServer) { | 339 setupServer(1, directRequestPaths: ["/4"], secure: true) |
337 HttpClient client = new HttpClient(context: clientContext); | 340 .then((secureServer) { |
| 341 HttpClient client = new HttpClient(context: clientContext); |
338 | 342 |
339 List<String> proxy; | 343 List<String> proxy; |
340 if (Platform.operatingSystem == "windows") { | 344 if (Platform.operatingSystem == "windows") { |
341 proxy = | 345 proxy = [ |
342 ["PROXY localhost:${proxyServer.port}", | 346 "PROXY localhost:${proxyServer.port}", |
343 "PROXY localhost:${proxyServer.port}; PROXY hede.hule.hest:8080", | 347 "PROXY localhost:${proxyServer.port}; PROXY hede.hule.hest:8080", |
344 "PROXY localhost:${proxyServer.port}", | 348 "PROXY localhost:${proxyServer.port}", |
345 "" | 349 "" |
346 " PROXY localhost:${proxyServer.port}", | 350 " PROXY localhost:${proxyServer.port}", |
347 "DIRECT", | 351 "DIRECT", |
348 "PROXY localhost:${proxyServer.port}; DIRECT"]; | 352 "PROXY localhost:${proxyServer.port}; DIRECT" |
349 } else { | 353 ]; |
350 proxy = | 354 } else { |
351 ["PROXY localhost:${proxyServer.port}", | 355 proxy = [ |
352 "PROXY localhost:${proxyServer.port}; PROXY hede.hule.hest:8080", | 356 "PROXY localhost:${proxyServer.port}", |
353 "PROXY hede.hule.hest:8080; PROXY localhost:${proxyServer.port}", | 357 "PROXY localhost:${proxyServer.port}; PROXY hede.hule.hest:8080", |
354 "PROXY hede.hule.hest:8080; PROXY hede.hule.hest:8181;" | 358 "PROXY hede.hule.hest:8080; PROXY localhost:${proxyServer.port}", |
355 " PROXY localhost:${proxyServer.port}", | 359 "PROXY hede.hule.hest:8080; PROXY hede.hule.hest:8181;" |
356 "PROXY hede.hule.hest:8080; PROXY hede.hule.hest:8181; DIRECT", | 360 " PROXY localhost:${proxyServer.port}", |
357 "PROXY localhost:${proxyServer.port}; DIRECT"]; | 361 "PROXY hede.hule.hest:8080; PROXY hede.hule.hest:8181; DIRECT", |
358 } | 362 "PROXY localhost:${proxyServer.port}; DIRECT" |
359 client.findProxy = (Uri uri) { | 363 ]; |
360 // Pick the proxy configuration based on the request path. | 364 } |
361 int index = int.parse(uri.path.substring(1)); | 365 client.findProxy = (Uri uri) { |
362 return proxy[index]; | 366 // Pick the proxy configuration based on the request path. |
363 }; | 367 int index = int.parse(uri.path.substring(1)); |
| 368 return proxy[index]; |
| 369 }; |
364 | 370 |
365 for (int i = 0; i < proxy.length; i++) { | 371 for (int i = 0; i < proxy.length; i++) { |
366 test(bool secure) { | 372 test(bool secure) { |
367 String url = secure | 373 String url = secure |
368 ? "https://localhost:${secureServer.port}/$i" | 374 ? "https://localhost:${secureServer.port}/$i" |
369 : "http://localhost:${server.port}/$i"; | 375 : "http://localhost:${server.port}/$i"; |
370 | 376 |
371 client.postUrl(Uri.parse(url)) | 377 client |
372 .then((HttpClientRequest clientRequest) { | 378 .postUrl(Uri.parse(url)) |
373 String content = "$i$i$i"; | 379 .then((HttpClientRequest clientRequest) { |
374 clientRequest.write(content); | 380 String content = "$i$i$i"; |
375 return clientRequest.close(); | 381 clientRequest.write(content); |
376 }) | 382 return clientRequest.close(); |
377 .then((HttpClientResponse response) { | 383 }).then((HttpClientResponse response) { |
378 response.listen((_) {}, onDone: () { | 384 response.listen((_) {}, onDone: () { |
379 testProxyDoneCount++; | 385 testProxyDoneCount++; |
380 if (testProxyDoneCount == proxy.length * 2) { | 386 if (testProxyDoneCount == proxy.length * 2) { |
381 Expect.equals(proxy.length, server.requestCount); | 387 Expect.equals(proxy.length, server.requestCount); |
382 Expect.equals(proxy.length, secureServer.requestCount); | 388 Expect.equals(proxy.length, secureServer.requestCount); |
383 proxyServer.shutdown(); | 389 proxyServer.shutdown(); |
384 server.shutdown(); | 390 server.shutdown(); |
385 secureServer.shutdown(); | 391 secureServer.shutdown(); |
386 client.close(); | 392 client.close(); |
387 } | 393 } |
| 394 }); |
388 }); | 395 }); |
389 }); | 396 } |
390 } | |
391 | 397 |
392 test(false); | 398 test(false); |
393 test(true); | 399 test(true); |
394 } | 400 } |
395 }); | 401 }); |
396 }); | 402 }); |
397 }); | 403 }); |
398 } | 404 } |
399 | 405 |
400 | |
401 int testProxyChainDoneCount = 0; | 406 int testProxyChainDoneCount = 0; |
402 void testProxyChain() { | 407 void testProxyChain() { |
403 // Setup two proxy servers having the first using the second as its proxy. | 408 // Setup two proxy servers having the first using the second as its proxy. |
404 setupProxyServer().then((proxyServer1) { | 409 setupProxyServer().then((proxyServer1) { |
405 setupProxyServer().then((proxyServer2) { | 410 setupProxyServer().then((proxyServer2) { |
406 proxyServer1.client.findProxy = (_) => "PROXY localhost:${proxyServer2.port}"; | 411 proxyServer1.client.findProxy = |
| 412 (_) => "PROXY localhost:${proxyServer2.port}"; |
407 | 413 |
408 setupServer(2, directRequestPaths: ["/4"]).then((server) { | 414 setupServer(2, directRequestPaths: ["/4"]).then((server) { |
409 HttpClient client = new HttpClient(context: clientContext); | 415 HttpClient client = new HttpClient(context: clientContext); |
410 | 416 |
411 List<String> proxy; | 417 List<String> proxy; |
412 if (Platform.operatingSystem == "windows") { | 418 if (Platform.operatingSystem == "windows") { |
413 proxy = | 419 proxy = [ |
414 ["PROXY localhost:${proxyServer1.port}", | 420 "PROXY localhost:${proxyServer1.port}", |
415 "PROXY localhost:${proxyServer1.port}; PROXY hede.hule.hest:8080", | 421 "PROXY localhost:${proxyServer1.port}; PROXY hede.hule.hest:8080", |
416 "PROXY localhost:${proxyServer1.port}", | 422 "PROXY localhost:${proxyServer1.port}", |
417 "PROXY localhost:${proxyServer1.port}", | 423 "PROXY localhost:${proxyServer1.port}", |
418 "DIRECT", | 424 "DIRECT", |
419 "PROXY localhost:${proxyServer1.port}; DIRECT"]; | 425 "PROXY localhost:${proxyServer1.port}; DIRECT" |
420 } else { | 426 ]; |
421 proxy = | 427 } else { |
422 ["PROXY localhost:${proxyServer1.port}", | 428 proxy = [ |
423 "PROXY localhost:${proxyServer1.port}; PROXY hede.hule.hest:8080", | 429 "PROXY localhost:${proxyServer1.port}", |
424 "PROXY hede.hule.hest:8080; PROXY localhost:${proxyServer1.port}", | 430 "PROXY localhost:${proxyServer1.port}; PROXY hede.hule.hest:8080", |
425 "PROXY hede.hule.hest:8080; PROXY hede.hule.hest:8181;" | 431 "PROXY hede.hule.hest:8080; PROXY localhost:${proxyServer1.port}", |
426 " PROXY localhost:${proxyServer1.port}", | 432 "PROXY hede.hule.hest:8080; PROXY hede.hule.hest:8181;" |
427 "PROXY hede.hule.hest:8080; PROXY hede.hule.hest:8181; DIRECT", | 433 " PROXY localhost:${proxyServer1.port}", |
428 "PROXY localhost:${proxyServer1.port}; DIRECT"]; | 434 "PROXY hede.hule.hest:8080; PROXY hede.hule.hest:8181; DIRECT", |
429 } | 435 "PROXY localhost:${proxyServer1.port}; DIRECT" |
| 436 ]; |
| 437 } |
430 | 438 |
431 client.findProxy = (Uri uri) { | 439 client.findProxy = (Uri uri) { |
432 // Pick the proxy configuration based on the request path. | 440 // Pick the proxy configuration based on the request path. |
433 int index = int.parse(uri.path.substring(1)); | 441 int index = int.parse(uri.path.substring(1)); |
434 return proxy[index]; | 442 return proxy[index]; |
435 }; | 443 }; |
436 | 444 |
437 for (int i = 0; i < proxy.length; i++) { | 445 for (int i = 0; i < proxy.length; i++) { |
438 client.getUrl(Uri.parse("http://localhost:${server.port}/$i")) | 446 client |
439 .then((HttpClientRequest clientRequest) { | 447 .getUrl(Uri.parse("http://localhost:${server.port}/$i")) |
440 String content = "$i$i$i"; | 448 .then((HttpClientRequest clientRequest) { |
441 clientRequest.contentLength = content.length; | 449 String content = "$i$i$i"; |
442 clientRequest.write(content); | 450 clientRequest.contentLength = content.length; |
443 return clientRequest.close(); | 451 clientRequest.write(content); |
444 }) | 452 return clientRequest.close(); |
445 .then((HttpClientResponse response) { | 453 }).then((HttpClientResponse response) { |
446 response.listen((_) {}, onDone: () { | 454 response.listen((_) {}, onDone: () { |
447 testProxyChainDoneCount++; | 455 testProxyChainDoneCount++; |
448 if (testProxyChainDoneCount == proxy.length) { | 456 if (testProxyChainDoneCount == proxy.length) { |
449 Expect.equals(proxy.length, server.requestCount); | 457 Expect.equals(proxy.length, server.requestCount); |
450 proxyServer1.shutdown(); | 458 proxyServer1.shutdown(); |
451 proxyServer2.shutdown(); | 459 proxyServer2.shutdown(); |
452 server.shutdown(); | 460 server.shutdown(); |
453 client.close(); | 461 client.close(); |
454 } | 462 } |
| 463 }); |
455 }); | 464 }); |
456 }); | 465 } |
457 } | 466 }); |
458 }); | 467 }); |
459 }); | |
460 }); | 468 }); |
461 } | 469 } |
462 | 470 |
463 main() { | 471 main() { |
464 testInvalidProxy(); | 472 testInvalidProxy(); |
465 testDirectProxy(); | 473 testDirectProxy(); |
466 testProxy(); | 474 testProxy(); |
467 testProxyChain(); | 475 testProxyChain(); |
468 } | 476 } |
OLD | NEW |