| 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 |