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 |