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 |