| 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 part of dart.io; | 5 part of dart.io; |
| 6 | 6 |
| 7 class _HttpIncoming extends Stream<List<int>> { | 7 class _HttpIncoming extends Stream<List<int>> { |
| 8 final int _transferLength; | 8 final int _transferLength; |
| 9 final Completer _dataCompleter = new Completer(); | 9 final Completer _dataCompleter = new Completer(); |
| 10 Stream<List<int>> _stream; | 10 Stream<List<int>> _stream; |
| (...skipping 909 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 920 return result; | 920 return result; |
| 921 } | 921 } |
| 922 | 922 |
| 923 if (_proxy.isDirect) { | 923 if (_proxy.isDirect) { |
| 924 return uriStartingFromPath(); | 924 return uriStartingFromPath(); |
| 925 } else { | 925 } else { |
| 926 if (method == "CONNECT") { | 926 if (method == "CONNECT") { |
| 927 // For the connect method the request URI is the host:port of | 927 // For the connect method the request URI is the host:port of |
| 928 // the requested destination of the tunnel (see RFC 2817 | 928 // the requested destination of the tunnel (see RFC 2817 |
| 929 // section 5.2) | 929 // section 5.2) |
| 930 return "${uri.domain}:${uri.port}"; | 930 return "${uri.host}:${uri.port}"; |
| 931 } else { | 931 } else { |
| 932 if (_httpClientConnection._proxyTunnel) { | 932 if (_httpClientConnection._proxyTunnel) { |
| 933 return uriStartingFromPath(); | 933 return uriStartingFromPath(); |
| 934 } else { | 934 } else { |
| 935 return uri.toString(); | 935 return uri.toString(); |
| 936 } | 936 } |
| 937 } | 937 } |
| 938 } | 938 } |
| 939 } | 939 } |
| 940 | 940 |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1129 _ProxyCredentials proxyCreds; // Credentials used to authorize proxy. | 1129 _ProxyCredentials proxyCreds; // Credentials used to authorize proxy. |
| 1130 _SiteCredentials creds; // Credentials used to authorize this request. | 1130 _SiteCredentials creds; // Credentials used to authorize this request. |
| 1131 var outgoing = new _HttpOutgoing(_socket); | 1131 var outgoing = new _HttpOutgoing(_socket); |
| 1132 // Create new request object, wrapping the outgoing connection. | 1132 // Create new request object, wrapping the outgoing connection. |
| 1133 var request = new _HttpClientRequest(outgoing, | 1133 var request = new _HttpClientRequest(outgoing, |
| 1134 uri, | 1134 uri, |
| 1135 method, | 1135 method, |
| 1136 proxy, | 1136 proxy, |
| 1137 _httpClient, | 1137 _httpClient, |
| 1138 this); | 1138 this); |
| 1139 request.headers.host = uri.domain; | 1139 request.headers.host = uri.host; |
| 1140 request.headers.port = port; | 1140 request.headers.port = port; |
| 1141 request.headers.set(HttpHeaders.ACCEPT_ENCODING, "gzip"); | 1141 request.headers.set(HttpHeaders.ACCEPT_ENCODING, "gzip"); |
| 1142 if (proxy.isAuthenticated) { | 1142 if (proxy.isAuthenticated) { |
| 1143 // If the proxy configuration contains user information use that | 1143 // If the proxy configuration contains user information use that |
| 1144 // for proxy basic authorization. | 1144 // for proxy basic authorization. |
| 1145 String auth = CryptoUtils.bytesToBase64( | 1145 String auth = CryptoUtils.bytesToBase64( |
| 1146 _encodeString("${proxy.username}:${proxy.password}")); | 1146 _encodeString("${proxy.username}:${proxy.password}")); |
| 1147 request.headers.set(HttpHeaders.PROXY_AUTHORIZATION, "Basic $auth"); | 1147 request.headers.set(HttpHeaders.PROXY_AUTHORIZATION, "Basic $auth"); |
| 1148 } else if (!proxy.isDirect && _httpClient._proxyCredentials.length > 0) { | 1148 } else if (!proxy.isDirect && _httpClient._proxyCredentials.length > 0) { |
| 1149 proxyCreds = _httpClient._findProxyCredentials(proxy); | 1149 proxyCreds = _httpClient._findProxyCredentials(proxy); |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1252 void close() { | 1252 void close() { |
| 1253 closed = true; | 1253 closed = true; |
| 1254 _httpClient._connectionClosed(this); | 1254 _httpClient._connectionClosed(this); |
| 1255 _streamFuture | 1255 _streamFuture |
| 1256 // TODO(ajohnsen): Add timeout. | 1256 // TODO(ajohnsen): Add timeout. |
| 1257 .then((_) => _socket.destroy()); | 1257 .then((_) => _socket.destroy()); |
| 1258 } | 1258 } |
| 1259 | 1259 |
| 1260 Future<_HttpClientConnection> createProxyTunnel(host, port, proxy) { | 1260 Future<_HttpClientConnection> createProxyTunnel(host, port, proxy) { |
| 1261 _HttpClientRequest request = | 1261 _HttpClientRequest request = |
| 1262 send(new Uri.fromComponents(domain: host, port: port), | 1262 send(new Uri(host: host, port: port), |
| 1263 port, | 1263 port, |
| 1264 "CONNECT", | 1264 "CONNECT", |
| 1265 proxy); | 1265 proxy); |
| 1266 if (proxy.isAuthenticated) { | 1266 if (proxy.isAuthenticated) { |
| 1267 // If the proxy configuration contains user information use that | 1267 // If the proxy configuration contains user information use that |
| 1268 // for proxy basic authorization. | 1268 // for proxy basic authorization. |
| 1269 String auth = CryptoUtils.bytesToBase64( | 1269 String auth = CryptoUtils.bytesToBase64( |
| 1270 _encodeString("${proxy.username}:${proxy.password}")); | 1270 _encodeString("${proxy.username}:${proxy.password}")); |
| 1271 request.headers.set(HttpHeaders.PROXY_AUTHORIZATION, "Basic $auth"); | 1271 request.headers.set(HttpHeaders.PROXY_AUTHORIZATION, "Basic $auth"); |
| 1272 } | 1272 } |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1345 c.startTimer(); | 1345 c.startTimer(); |
| 1346 })); | 1346 })); |
| 1347 } | 1347 } |
| 1348 | 1348 |
| 1349 Future<HttpClientRequest> open(String method, | 1349 Future<HttpClientRequest> open(String method, |
| 1350 String host, | 1350 String host, |
| 1351 int port, | 1351 int port, |
| 1352 String path) { | 1352 String path) { |
| 1353 // TODO(sgjesse): The path set here can contain both query and | 1353 // TODO(sgjesse): The path set here can contain both query and |
| 1354 // fragment. They should be cracked and set correctly. | 1354 // fragment. They should be cracked and set correctly. |
| 1355 return _openUrl(method, new Uri.fromComponents( | 1355 return _openUrl(method, new Uri( |
| 1356 scheme: "http", domain: host, port: port, path: path)); | 1356 scheme: "http", host: host, port: port, path: path)); |
| 1357 } | 1357 } |
| 1358 | 1358 |
| 1359 Future<HttpClientRequest> openUrl(String method, Uri url) { | 1359 Future<HttpClientRequest> openUrl(String method, Uri url) { |
| 1360 return _openUrl(method, url); | 1360 return _openUrl(method, url); |
| 1361 } | 1361 } |
| 1362 | 1362 |
| 1363 Future<HttpClientRequest> get(String host, | 1363 Future<HttpClientRequest> get(String host, |
| 1364 int port, | 1364 int port, |
| 1365 String path) { | 1365 String path) { |
| 1366 return open("get", host, port, path); | 1366 return open("get", host, port, path); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1423 _proxyCredentials.add(new _ProxyCredentials(host, port, realm, cr)); | 1423 _proxyCredentials.add(new _ProxyCredentials(host, port, realm, cr)); |
| 1424 } | 1424 } |
| 1425 | 1425 |
| 1426 set findProxy(String f(Uri uri)) => _findProxy = f; | 1426 set findProxy(String f(Uri uri)) => _findProxy = f; |
| 1427 | 1427 |
| 1428 Future<HttpClientRequest> _openUrl(String method, Uri uri) { | 1428 Future<HttpClientRequest> _openUrl(String method, Uri uri) { |
| 1429 if (method == null) { | 1429 if (method == null) { |
| 1430 throw new ArgumentError(method); | 1430 throw new ArgumentError(method); |
| 1431 } | 1431 } |
| 1432 if (method != "CONNECT") { | 1432 if (method != "CONNECT") { |
| 1433 if (uri.domain.isEmpty || | 1433 if (uri.host.isEmpty || |
| 1434 (uri.scheme != "http" && uri.scheme != "https")) { | 1434 (uri.scheme != "http" && uri.scheme != "https")) { |
| 1435 throw new ArgumentError("Unsupported scheme '${uri.scheme}' in $uri"); | 1435 throw new ArgumentError("Unsupported scheme '${uri.scheme}' in $uri"); |
| 1436 } | 1436 } |
| 1437 } | 1437 } |
| 1438 | 1438 |
| 1439 bool isSecure = (uri.scheme == "https"); | 1439 bool isSecure = (uri.scheme == "https"); |
| 1440 int port = uri.port; | 1440 int port = uri.port; |
| 1441 if (port == 0) { | 1441 if (port == 0) { |
| 1442 port = isSecure ? | 1442 port = isSecure ? |
| 1443 HttpClient.DEFAULT_HTTPS_PORT : | 1443 HttpClient.DEFAULT_HTTPS_PORT : |
| 1444 HttpClient.DEFAULT_HTTP_PORT; | 1444 HttpClient.DEFAULT_HTTP_PORT; |
| 1445 } | 1445 } |
| 1446 // Check to see if a proxy server should be used for this connection. | 1446 // Check to see if a proxy server should be used for this connection. |
| 1447 var proxyConf = const _ProxyConfiguration.direct(); | 1447 var proxyConf = const _ProxyConfiguration.direct(); |
| 1448 if (_findProxy != null) { | 1448 if (_findProxy != null) { |
| 1449 // TODO(sgjesse): Keep a map of these as normally only a few | 1449 // TODO(sgjesse): Keep a map of these as normally only a few |
| 1450 // configuration strings will be used. | 1450 // configuration strings will be used. |
| 1451 try { | 1451 try { |
| 1452 proxyConf = new _ProxyConfiguration(_findProxy(uri)); | 1452 proxyConf = new _ProxyConfiguration(_findProxy(uri)); |
| 1453 } catch (error, stackTrace) { | 1453 } catch (error, stackTrace) { |
| 1454 return new Future.error(error, stackTrace); | 1454 return new Future.error(error, stackTrace); |
| 1455 } | 1455 } |
| 1456 } | 1456 } |
| 1457 return _getConnection(uri.domain, port, proxyConf, isSecure) | 1457 return _getConnection(uri.host, port, proxyConf, isSecure) |
| 1458 .then((info) { | 1458 .then((info) { |
| 1459 send(info) { | 1459 send(info) { |
| 1460 return info.connection.send(uri, | 1460 return info.connection.send(uri, |
| 1461 port, | 1461 port, |
| 1462 method.toUpperCase(), | 1462 method.toUpperCase(), |
| 1463 info.proxy); | 1463 info.proxy); |
| 1464 } | 1464 } |
| 1465 // If the connection was closed before the request was sent, create | 1465 // If the connection was closed before the request was sent, create |
| 1466 // and use another connection. | 1466 // and use another connection. |
| 1467 if (info.connection.closed) { | 1467 if (info.connection.closed) { |
| 1468 return _getConnection(uri.domain, port, proxyConf, isSecure) | 1468 return _getConnection(uri.host, port, proxyConf, isSecure) |
| 1469 .then(send); | 1469 .then(send); |
| 1470 } | 1470 } |
| 1471 return send(info); | 1471 return send(info); |
| 1472 }); | 1472 }); |
| 1473 } | 1473 } |
| 1474 | 1474 |
| 1475 Future<HttpClientRequest> _openUrlFromRequest(String method, | 1475 Future<HttpClientRequest> _openUrlFromRequest(String method, |
| 1476 Uri uri, | 1476 Uri uri, |
| 1477 _HttpClientRequest previous) { | 1477 _HttpClientRequest previous) { |
| 1478 // If the new URI is relative (to either '/' or some sub-path), | 1478 // If the new URI is relative (to either '/' or some sub-path), |
| 1479 // construct a full URI from the previous one. | 1479 // construct a full URI from the previous one. |
| 1480 // See http://tools.ietf.org/html/rfc3986#section-4.2 | 1480 // See http://tools.ietf.org/html/rfc3986#section-4.2 |
| 1481 replaceComponents({scheme, domain, port, path}) { | 1481 replaceComponents({scheme, host, port, path}) { |
| 1482 uri = new Uri.fromComponents( | 1482 uri = new Uri( |
| 1483 scheme: scheme != null ? scheme : uri.scheme, | 1483 scheme: scheme != null ? scheme : uri.scheme, |
| 1484 domain: domain != null ? domain : uri.domain, | 1484 host: host != null ? host : uri.host, |
| 1485 port: port != null ? port : uri.port, | 1485 port: port != null ? port : uri.port, |
| 1486 path: path != null ? path : uri.path, | 1486 path: path != null ? path : uri.path, |
| 1487 query: uri.query, | 1487 query: uri.query, |
| 1488 fragment: uri.fragment); | 1488 fragment: uri.fragment); |
| 1489 } | 1489 } |
| 1490 if (uri.domain == '') { | 1490 if (uri.host.isEmpty) { |
| 1491 replaceComponents(domain: previous.uri.domain, port: previous.uri.port); | 1491 replaceComponents(host: previous.uri.host, port: previous.uri.port); |
| 1492 } | 1492 } |
| 1493 if (uri.scheme == '') { | 1493 if (uri.scheme.isEmpty) { |
| 1494 replaceComponents(scheme: previous.uri.scheme); | 1494 replaceComponents(scheme: previous.uri.scheme); |
| 1495 } | 1495 } |
| 1496 if (!uri.path.startsWith('/') && previous.uri.path.startsWith('/')) { | 1496 if (!uri.path.startsWith('/') && previous.uri.path.startsWith('/')) { |
| 1497 var absolute = new Path.raw(previous.uri.path).directoryPath; | 1497 var absolute = new Path.raw(previous.uri.path).directoryPath; |
| 1498 absolute = absolute.join(new Path.raw(uri.path)); | 1498 absolute = absolute.join(new Path.raw(uri.path)); |
| 1499 replaceComponents(path: absolute.canonicalize().toString()); | 1499 replaceComponents(path: absolute.canonicalize().toString()); |
| 1500 } | 1500 } |
| 1501 return openUrl(method, uri).then((_HttpClientRequest request) { | 1501 return openUrl(method, uri).then((_HttpClientRequest request) { |
| 1502 // Only follow redirects if initial request did. | 1502 // Only follow redirects if initial request did. |
| 1503 request.followRedirects = previous.followRedirects; | 1503 request.followRedirects = previous.followRedirects; |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1650 _proxyCredentials.removeAt(index); | 1650 _proxyCredentials.removeAt(index); |
| 1651 } | 1651 } |
| 1652 } | 1652 } |
| 1653 | 1653 |
| 1654 static String _findProxyFromEnvironment(Uri url, | 1654 static String _findProxyFromEnvironment(Uri url, |
| 1655 Map<String, String> environment) { | 1655 Map<String, String> environment) { |
| 1656 checkNoProxy(String option) { | 1656 checkNoProxy(String option) { |
| 1657 if (option == null) return null; | 1657 if (option == null) return null; |
| 1658 Iterator<String> names = option.split(",").map((s) => s.trim()).iterator; | 1658 Iterator<String> names = option.split(",").map((s) => s.trim()).iterator; |
| 1659 while (names.moveNext()) { | 1659 while (names.moveNext()) { |
| 1660 if (url.domain.endsWith(names.current)) { | 1660 if (url.host.endsWith(names.current)) { |
| 1661 return "DIRECT"; | 1661 return "DIRECT"; |
| 1662 } | 1662 } |
| 1663 } | 1663 } |
| 1664 return null; | 1664 return null; |
| 1665 } | 1665 } |
| 1666 | 1666 |
| 1667 checkProxy(String option) { | 1667 checkProxy(String option) { |
| 1668 if (option == null) return null; | 1668 if (option == null) return null; |
| 1669 int pos = option.indexOf("://"); | 1669 int pos = option.indexOf("://"); |
| 1670 if (pos >= 0) { | 1670 if (pos >= 0) { |
| (...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2146 } | 2146 } |
| 2147 | 2147 |
| 2148 class _SiteCredentials extends _Credentials { | 2148 class _SiteCredentials extends _Credentials { |
| 2149 Uri uri; | 2149 Uri uri; |
| 2150 | 2150 |
| 2151 _SiteCredentials(this.uri, realm, _HttpClientCredentials creds) | 2151 _SiteCredentials(this.uri, realm, _HttpClientCredentials creds) |
| 2152 : super(creds, realm); | 2152 : super(creds, realm); |
| 2153 | 2153 |
| 2154 bool applies(Uri uri, _AuthenticationScheme scheme) { | 2154 bool applies(Uri uri, _AuthenticationScheme scheme) { |
| 2155 if (scheme != null && credentials.scheme != scheme) return false; | 2155 if (scheme != null && credentials.scheme != scheme) return false; |
| 2156 if (uri.domain != this.uri.domain) return false; | 2156 if (uri.host != this.uri.host) return false; |
| 2157 int thisPort = | 2157 int thisPort = |
| 2158 this.uri.port == 0 ? HttpClient.DEFAULT_HTTP_PORT : this.uri.port; | 2158 this.uri.port == 0 ? HttpClient.DEFAULT_HTTP_PORT : this.uri.port; |
| 2159 int otherPort = uri.port == 0 ? HttpClient.DEFAULT_HTTP_PORT : uri.port; | 2159 int otherPort = uri.port == 0 ? HttpClient.DEFAULT_HTTP_PORT : uri.port; |
| 2160 if (otherPort != thisPort) return false; | 2160 if (otherPort != thisPort) return false; |
| 2161 return uri.path.startsWith(this.uri.path); | 2161 return uri.path.startsWith(this.uri.path); |
| 2162 } | 2162 } |
| 2163 | 2163 |
| 2164 void authorize(HttpClientRequest request) { | 2164 void authorize(HttpClientRequest request) { |
| 2165 // Digest credentials cannot be used without a nonce from the | 2165 // Digest credentials cannot be used without a nonce from the |
| 2166 // server. | 2166 // server. |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2319 | 2319 |
| 2320 | 2320 |
| 2321 class _RedirectInfo implements RedirectInfo { | 2321 class _RedirectInfo implements RedirectInfo { |
| 2322 const _RedirectInfo(int this.statusCode, | 2322 const _RedirectInfo(int this.statusCode, |
| 2323 String this.method, | 2323 String this.method, |
| 2324 Uri this.location); | 2324 Uri this.location); |
| 2325 final int statusCode; | 2325 final int statusCode; |
| 2326 final String method; | 2326 final String method; |
| 2327 final Uri location; | 2327 final Uri location; |
| 2328 } | 2328 } |
| OLD | NEW |