| 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 928 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 939 return result; | 939 return result; |
| 940 } | 940 } |
| 941 | 941 |
| 942 if (_proxy.isDirect) { | 942 if (_proxy.isDirect) { |
| 943 return uriStartingFromPath(); | 943 return uriStartingFromPath(); |
| 944 } else { | 944 } else { |
| 945 if (method == "CONNECT") { | 945 if (method == "CONNECT") { |
| 946 // For the connect method the request URI is the host:port of | 946 // For the connect method the request URI is the host:port of |
| 947 // the requested destination of the tunnel (see RFC 2817 | 947 // the requested destination of the tunnel (see RFC 2817 |
| 948 // section 5.2) | 948 // section 5.2) |
| 949 return "${uri.domain}:${uri.port}"; | 949 return "${uri.host}:${uri.port}"; |
| 950 } else { | 950 } else { |
| 951 if (_httpClientConnection._proxyTunnel) { | 951 if (_httpClientConnection._proxyTunnel) { |
| 952 return uriStartingFromPath(); | 952 return uriStartingFromPath(); |
| 953 } else { | 953 } else { |
| 954 return uri.toString(); | 954 return uri.toString(); |
| 955 } | 955 } |
| 956 } | 956 } |
| 957 } | 957 } |
| 958 } | 958 } |
| 959 | 959 |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1148 _ProxyCredentials proxyCreds; // Credentials used to authorize proxy. | 1148 _ProxyCredentials proxyCreds; // Credentials used to authorize proxy. |
| 1149 _SiteCredentials creds; // Credentials used to authorize this request. | 1149 _SiteCredentials creds; // Credentials used to authorize this request. |
| 1150 var outgoing = new _HttpOutgoing(_socket); | 1150 var outgoing = new _HttpOutgoing(_socket); |
| 1151 // Create new request object, wrapping the outgoing connection. | 1151 // Create new request object, wrapping the outgoing connection. |
| 1152 var request = new _HttpClientRequest(outgoing, | 1152 var request = new _HttpClientRequest(outgoing, |
| 1153 uri, | 1153 uri, |
| 1154 method, | 1154 method, |
| 1155 proxy, | 1155 proxy, |
| 1156 _httpClient, | 1156 _httpClient, |
| 1157 this); | 1157 this); |
| 1158 request.headers.host = uri.domain; | 1158 request.headers.host = uri.host; |
| 1159 request.headers.port = port; | 1159 request.headers.port = port; |
| 1160 request.headers.set(HttpHeaders.ACCEPT_ENCODING, "gzip"); | 1160 request.headers.set(HttpHeaders.ACCEPT_ENCODING, "gzip"); |
| 1161 if (proxy.isAuthenticated) { | 1161 if (proxy.isAuthenticated) { |
| 1162 // If the proxy configuration contains user information use that | 1162 // If the proxy configuration contains user information use that |
| 1163 // for proxy basic authorization. | 1163 // for proxy basic authorization. |
| 1164 String auth = CryptoUtils.bytesToBase64( | 1164 String auth = CryptoUtils.bytesToBase64( |
| 1165 _encodeString("${proxy.username}:${proxy.password}")); | 1165 _encodeString("${proxy.username}:${proxy.password}")); |
| 1166 request.headers.set(HttpHeaders.PROXY_AUTHORIZATION, "Basic $auth"); | 1166 request.headers.set(HttpHeaders.PROXY_AUTHORIZATION, "Basic $auth"); |
| 1167 } else if (!proxy.isDirect && _httpClient._proxyCredentials.length > 0) { | 1167 } else if (!proxy.isDirect && _httpClient._proxyCredentials.length > 0) { |
| 1168 proxyCreds = _httpClient._findProxyCredentials(proxy); | 1168 proxyCreds = _httpClient._findProxyCredentials(proxy); |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1271 void close() { | 1271 void close() { |
| 1272 closed = true; | 1272 closed = true; |
| 1273 _httpClient._connectionClosed(this); | 1273 _httpClient._connectionClosed(this); |
| 1274 _streamFuture | 1274 _streamFuture |
| 1275 // TODO(ajohnsen): Add timeout. | 1275 // TODO(ajohnsen): Add timeout. |
| 1276 .then((_) => _socket.destroy()); | 1276 .then((_) => _socket.destroy()); |
| 1277 } | 1277 } |
| 1278 | 1278 |
| 1279 Future<_HttpClientConnection> createProxyTunnel(host, port, proxy) { | 1279 Future<_HttpClientConnection> createProxyTunnel(host, port, proxy) { |
| 1280 _HttpClientRequest request = | 1280 _HttpClientRequest request = |
| 1281 send(new Uri.fromComponents(domain: host, port: port), | 1281 send(new Uri(host: host, port: port), |
| 1282 port, | 1282 port, |
| 1283 "CONNECT", | 1283 "CONNECT", |
| 1284 proxy); | 1284 proxy); |
| 1285 if (proxy.isAuthenticated) { | 1285 if (proxy.isAuthenticated) { |
| 1286 // If the proxy configuration contains user information use that | 1286 // If the proxy configuration contains user information use that |
| 1287 // for proxy basic authorization. | 1287 // for proxy basic authorization. |
| 1288 String auth = CryptoUtils.bytesToBase64( | 1288 String auth = CryptoUtils.bytesToBase64( |
| 1289 _encodeString("${proxy.username}:${proxy.password}")); | 1289 _encodeString("${proxy.username}:${proxy.password}")); |
| 1290 request.headers.set(HttpHeaders.PROXY_AUTHORIZATION, "Basic $auth"); | 1290 request.headers.set(HttpHeaders.PROXY_AUTHORIZATION, "Basic $auth"); |
| 1291 } | 1291 } |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1364 c.startTimer(); | 1364 c.startTimer(); |
| 1365 })); | 1365 })); |
| 1366 } | 1366 } |
| 1367 | 1367 |
| 1368 Future<HttpClientRequest> open(String method, | 1368 Future<HttpClientRequest> open(String method, |
| 1369 String host, | 1369 String host, |
| 1370 int port, | 1370 int port, |
| 1371 String path) { | 1371 String path) { |
| 1372 // TODO(sgjesse): The path set here can contain both query and | 1372 // TODO(sgjesse): The path set here can contain both query and |
| 1373 // fragment. They should be cracked and set correctly. | 1373 // fragment. They should be cracked and set correctly. |
| 1374 return _openUrl(method, new Uri.fromComponents( | 1374 return _openUrl(method, new Uri( |
| 1375 scheme: "http", domain: host, port: port, path: path)); | 1375 scheme: "http", host: host, port: port, path: path)); |
| 1376 } | 1376 } |
| 1377 | 1377 |
| 1378 Future<HttpClientRequest> openUrl(String method, Uri url) { | 1378 Future<HttpClientRequest> openUrl(String method, Uri url) { |
| 1379 return _openUrl(method, url); | 1379 return _openUrl(method, url); |
| 1380 } | 1380 } |
| 1381 | 1381 |
| 1382 Future<HttpClientRequest> get(String host, | 1382 Future<HttpClientRequest> get(String host, |
| 1383 int port, | 1383 int port, |
| 1384 String path) { | 1384 String path) { |
| 1385 return open("get", host, port, path); | 1385 return open("get", host, port, path); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1442 _proxyCredentials.add(new _ProxyCredentials(host, port, realm, cr)); | 1442 _proxyCredentials.add(new _ProxyCredentials(host, port, realm, cr)); |
| 1443 } | 1443 } |
| 1444 | 1444 |
| 1445 set findProxy(String f(Uri uri)) => _findProxy = f; | 1445 set findProxy(String f(Uri uri)) => _findProxy = f; |
| 1446 | 1446 |
| 1447 Future<HttpClientRequest> _openUrl(String method, Uri uri) { | 1447 Future<HttpClientRequest> _openUrl(String method, Uri uri) { |
| 1448 if (method == null) { | 1448 if (method == null) { |
| 1449 throw new ArgumentError(method); | 1449 throw new ArgumentError(method); |
| 1450 } | 1450 } |
| 1451 if (method != "CONNECT") { | 1451 if (method != "CONNECT") { |
| 1452 if (uri.domain.isEmpty || | 1452 if (uri.host.isEmpty || |
| 1453 (uri.scheme != "http" && uri.scheme != "https")) { | 1453 (uri.scheme != "http" && uri.scheme != "https")) { |
| 1454 throw new ArgumentError("Unsupported scheme '${uri.scheme}' in $uri"); | 1454 throw new ArgumentError("Unsupported scheme '${uri.scheme}' in $uri"); |
| 1455 } | 1455 } |
| 1456 } | 1456 } |
| 1457 | 1457 |
| 1458 bool isSecure = (uri.scheme == "https"); | 1458 bool isSecure = (uri.scheme == "https"); |
| 1459 int port = uri.port; | 1459 int port = uri.port; |
| 1460 if (port == 0) { | 1460 if (port == 0) { |
| 1461 port = isSecure ? | 1461 port = isSecure ? |
| 1462 HttpClient.DEFAULT_HTTPS_PORT : | 1462 HttpClient.DEFAULT_HTTPS_PORT : |
| 1463 HttpClient.DEFAULT_HTTP_PORT; | 1463 HttpClient.DEFAULT_HTTP_PORT; |
| 1464 } | 1464 } |
| 1465 // Check to see if a proxy server should be used for this connection. | 1465 // Check to see if a proxy server should be used for this connection. |
| 1466 var proxyConf = const _ProxyConfiguration.direct(); | 1466 var proxyConf = const _ProxyConfiguration.direct(); |
| 1467 if (_findProxy != null) { | 1467 if (_findProxy != null) { |
| 1468 // TODO(sgjesse): Keep a map of these as normally only a few | 1468 // TODO(sgjesse): Keep a map of these as normally only a few |
| 1469 // configuration strings will be used. | 1469 // configuration strings will be used. |
| 1470 try { | 1470 try { |
| 1471 proxyConf = new _ProxyConfiguration(_findProxy(uri)); | 1471 proxyConf = new _ProxyConfiguration(_findProxy(uri)); |
| 1472 } catch (error, stackTrace) { | 1472 } catch (error, stackTrace) { |
| 1473 return new Future.error(error, stackTrace); | 1473 return new Future.error(error, stackTrace); |
| 1474 } | 1474 } |
| 1475 } | 1475 } |
| 1476 return _getConnection(uri.domain, port, proxyConf, isSecure) | 1476 return _getConnection(uri.host, port, proxyConf, isSecure) |
| 1477 .then((info) { | 1477 .then((info) { |
| 1478 send(info) { | 1478 send(info) { |
| 1479 return info.connection.send(uri, | 1479 return info.connection.send(uri, |
| 1480 port, | 1480 port, |
| 1481 method.toUpperCase(), | 1481 method.toUpperCase(), |
| 1482 info.proxy); | 1482 info.proxy); |
| 1483 } | 1483 } |
| 1484 // If the connection was closed before the request was sent, create | 1484 // If the connection was closed before the request was sent, create |
| 1485 // and use another connection. | 1485 // and use another connection. |
| 1486 if (info.connection.closed) { | 1486 if (info.connection.closed) { |
| 1487 return _getConnection(uri.domain, port, proxyConf, isSecure) | 1487 return _getConnection(uri.host, port, proxyConf, isSecure) |
| 1488 .then(send); | 1488 .then(send); |
| 1489 } | 1489 } |
| 1490 return send(info); | 1490 return send(info); |
| 1491 }); | 1491 }); |
| 1492 } | 1492 } |
| 1493 | 1493 |
| 1494 Future<HttpClientRequest> _openUrlFromRequest(String method, | 1494 Future<HttpClientRequest> _openUrlFromRequest(String method, |
| 1495 Uri uri, | 1495 Uri uri, |
| 1496 _HttpClientRequest previous) { | 1496 _HttpClientRequest previous) { |
| 1497 // If the new URI is relative (to either '/' or some sub-path), | 1497 // If the new URI is relative (to either '/' or some sub-path), |
| 1498 // construct a full URI from the previous one. | 1498 // construct a full URI from the previous one. |
| 1499 // See http://tools.ietf.org/html/rfc3986#section-4.2 | 1499 // See http://tools.ietf.org/html/rfc3986#section-4.2 |
| 1500 replaceComponents({scheme, domain, port, path}) { | 1500 replaceComponents({scheme, host, port, path}) { |
| 1501 uri = new Uri.fromComponents( | 1501 uri = new Uri( |
| 1502 scheme: scheme != null ? scheme : uri.scheme, | 1502 scheme: scheme != null ? scheme : uri.scheme, |
| 1503 domain: domain != null ? domain : uri.domain, | 1503 host: host != null ? host : uri.host, |
| 1504 port: port != null ? port : uri.port, | 1504 port: port != null ? port : uri.port, |
| 1505 path: path != null ? path : uri.path, | 1505 path: path != null ? path : uri.path, |
| 1506 query: uri.query, | 1506 query: uri.query, |
| 1507 fragment: uri.fragment); | 1507 fragment: uri.fragment); |
| 1508 } | 1508 } |
| 1509 if (uri.domain == '') { | 1509 if (uri.host.isEmpty) { |
| 1510 replaceComponents(domain: previous.uri.domain, port: previous.uri.port); | 1510 replaceComponents(host: previous.uri.host, port: previous.uri.port); |
| 1511 } | 1511 } |
| 1512 if (uri.scheme == '') { | 1512 if (uri.scheme.isEmpty) { |
| 1513 replaceComponents(scheme: previous.uri.scheme); | 1513 replaceComponents(scheme: previous.uri.scheme); |
| 1514 } | 1514 } |
| 1515 if (!uri.path.startsWith('/') && previous.uri.path.startsWith('/')) { | 1515 if (!uri.path.startsWith('/') && previous.uri.path.startsWith('/')) { |
| 1516 var absolute = new Path.raw(previous.uri.path).directoryPath; | 1516 var absolute = new Path.raw(previous.uri.path).directoryPath; |
| 1517 absolute = absolute.join(new Path.raw(uri.path)); | 1517 absolute = absolute.join(new Path.raw(uri.path)); |
| 1518 replaceComponents(path: absolute.canonicalize().toString()); | 1518 replaceComponents(path: absolute.canonicalize().toString()); |
| 1519 } | 1519 } |
| 1520 return openUrl(method, uri).then((_HttpClientRequest request) { | 1520 return openUrl(method, uri).then((_HttpClientRequest request) { |
| 1521 // Only follow redirects if initial request did. | 1521 // Only follow redirects if initial request did. |
| 1522 request.followRedirects = previous.followRedirects; | 1522 request.followRedirects = previous.followRedirects; |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1669 _proxyCredentials.removeAt(index); | 1669 _proxyCredentials.removeAt(index); |
| 1670 } | 1670 } |
| 1671 } | 1671 } |
| 1672 | 1672 |
| 1673 static String _findProxyFromEnvironment(Uri url, | 1673 static String _findProxyFromEnvironment(Uri url, |
| 1674 Map<String, String> environment) { | 1674 Map<String, String> environment) { |
| 1675 checkNoProxy(String option) { | 1675 checkNoProxy(String option) { |
| 1676 if (option == null) return null; | 1676 if (option == null) return null; |
| 1677 Iterator<String> names = option.split(",").map((s) => s.trim()).iterator; | 1677 Iterator<String> names = option.split(",").map((s) => s.trim()).iterator; |
| 1678 while (names.moveNext()) { | 1678 while (names.moveNext()) { |
| 1679 if (url.domain.endsWith(names.current)) { | 1679 if (url.host.endsWith(names.current)) { |
| 1680 return "DIRECT"; | 1680 return "DIRECT"; |
| 1681 } | 1681 } |
| 1682 } | 1682 } |
| 1683 return null; | 1683 return null; |
| 1684 } | 1684 } |
| 1685 | 1685 |
| 1686 checkProxy(String option) { | 1686 checkProxy(String option) { |
| 1687 if (option == null) return null; | 1687 if (option == null) return null; |
| 1688 int pos = option.indexOf("://"); | 1688 int pos = option.indexOf("://"); |
| 1689 if (pos >= 0) { | 1689 if (pos >= 0) { |
| (...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2165 } | 2165 } |
| 2166 | 2166 |
| 2167 class _SiteCredentials extends _Credentials { | 2167 class _SiteCredentials extends _Credentials { |
| 2168 Uri uri; | 2168 Uri uri; |
| 2169 | 2169 |
| 2170 _SiteCredentials(this.uri, realm, _HttpClientCredentials creds) | 2170 _SiteCredentials(this.uri, realm, _HttpClientCredentials creds) |
| 2171 : super(creds, realm); | 2171 : super(creds, realm); |
| 2172 | 2172 |
| 2173 bool applies(Uri uri, _AuthenticationScheme scheme) { | 2173 bool applies(Uri uri, _AuthenticationScheme scheme) { |
| 2174 if (scheme != null && credentials.scheme != scheme) return false; | 2174 if (scheme != null && credentials.scheme != scheme) return false; |
| 2175 if (uri.domain != this.uri.domain) return false; | 2175 if (uri.host != this.uri.host) return false; |
| 2176 int thisPort = | 2176 int thisPort = |
| 2177 this.uri.port == 0 ? HttpClient.DEFAULT_HTTP_PORT : this.uri.port; | 2177 this.uri.port == 0 ? HttpClient.DEFAULT_HTTP_PORT : this.uri.port; |
| 2178 int otherPort = uri.port == 0 ? HttpClient.DEFAULT_HTTP_PORT : uri.port; | 2178 int otherPort = uri.port == 0 ? HttpClient.DEFAULT_HTTP_PORT : uri.port; |
| 2179 if (otherPort != thisPort) return false; | 2179 if (otherPort != thisPort) return false; |
| 2180 return uri.path.startsWith(this.uri.path); | 2180 return uri.path.startsWith(this.uri.path); |
| 2181 } | 2181 } |
| 2182 | 2182 |
| 2183 void authorize(HttpClientRequest request) { | 2183 void authorize(HttpClientRequest request) { |
| 2184 // Digest credentials cannot be used without a nonce from the | 2184 // Digest credentials cannot be used without a nonce from the |
| 2185 // server. | 2185 // server. |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2338 | 2338 |
| 2339 | 2339 |
| 2340 class _RedirectInfo implements RedirectInfo { | 2340 class _RedirectInfo implements RedirectInfo { |
| 2341 const _RedirectInfo(int this.statusCode, | 2341 const _RedirectInfo(int this.statusCode, |
| 2342 String this.method, | 2342 String this.method, |
| 2343 Uri this.location); | 2343 Uri this.location); |
| 2344 final int statusCode; | 2344 final int statusCode; |
| 2345 final String method; | 2345 final String method; |
| 2346 final Uri location; | 2346 final Uri location; |
| 2347 } | 2347 } |
| OLD | NEW |