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 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
208 if (url == null) { | 208 if (url == null) { |
209 String location = headers.value(HttpHeaders.LOCATION); | 209 String location = headers.value(HttpHeaders.LOCATION); |
210 if (location == null) { | 210 if (location == null) { |
211 throw new StateError("Response has no Location header for redirect"); | 211 throw new StateError("Response has no Location header for redirect"); |
212 } | 212 } |
213 url = Uri.parse(location); | 213 url = Uri.parse(location); |
214 } | 214 } |
215 if (followLoops != true) { | 215 if (followLoops != true) { |
216 for (var redirect in redirects) { | 216 for (var redirect in redirects) { |
217 if (redirect.location == url) { | 217 if (redirect.location == url) { |
218 return new Future.immediateError( | 218 return new Future.error( |
219 new RedirectLoopException(redirects)); | 219 new RedirectLoopException(redirects)); |
220 } | 220 } |
221 } | 221 } |
222 } | 222 } |
223 return _httpClient._openUrlFromRequest(method, url, _httpRequest) | 223 return _httpClient._openUrlFromRequest(method, url, _httpRequest) |
224 .then((request) { | 224 .then((request) { |
225 request._responseRedirects.addAll(this.redirects); | 225 request._responseRedirects.addAll(this.redirects); |
226 request._responseRedirects.add(new _RedirectInfo(statusCode, | 226 request._responseRedirects.add(new _RedirectInfo(statusCode, |
227 method, | 227 method, |
228 url)); | 228 url)); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
275 return _httpClient._openUrlFromRequest(_httpRequest.method, | 275 return _httpClient._openUrlFromRequest(_httpRequest.method, |
276 _httpRequest.uri, | 276 _httpRequest.uri, |
277 _httpRequest) | 277 _httpRequest) |
278 .then((request) => request.close()); | 278 .then((request) => request.close()); |
279 }); | 279 }); |
280 } | 280 } |
281 } | 281 } |
282 | 282 |
283 // Fall through to here to perform normal response handling if | 283 // Fall through to here to perform normal response handling if |
284 // there is no sensible authorization handling. | 284 // there is no sensible authorization handling. |
285 return new Future.immediate(this); | 285 return new Future.value(this); |
286 } | 286 } |
287 | 287 |
288 List<String> challenge = headers[HttpHeaders.WWW_AUTHENTICATE]; | 288 List<String> challenge = headers[HttpHeaders.WWW_AUTHENTICATE]; |
289 assert(challenge != null || challenge.length == 1); | 289 assert(challenge != null || challenge.length == 1); |
290 _HeaderValue header = | 290 _HeaderValue header = |
291 new _HeaderValue.fromString(challenge[0], parameterSeparator: ","); | 291 new _HeaderValue.fromString(challenge[0], parameterSeparator: ","); |
292 _AuthenticationScheme scheme = | 292 _AuthenticationScheme scheme = |
293 new _AuthenticationScheme.fromString(header.value); | 293 new _AuthenticationScheme.fromString(header.value); |
294 String realm = header.parameters["realm"]; | 294 String realm = header.parameters["realm"]; |
295 | 295 |
(...skipping 21 matching lines...) Expand all Loading... |
317 cr = _httpClient._findCredentials(_httpRequest.uri, scheme); | 317 cr = _httpClient._findCredentials(_httpRequest.uri, scheme); |
318 return retryWithCredentials(cr); | 318 return retryWithCredentials(cr); |
319 } else { | 319 } else { |
320 // No credentials available, complete with original response. | 320 // No credentials available, complete with original response. |
321 return this; | 321 return this; |
322 } | 322 } |
323 }); | 323 }); |
324 } | 324 } |
325 | 325 |
326 // No credentials were found and the callback was not set. | 326 // No credentials were found and the callback was not set. |
327 return new Future.immediate(this); | 327 return new Future.value(this); |
328 } | 328 } |
329 | 329 |
330 Future<HttpClientResponse> _authenticateProxy() { | 330 Future<HttpClientResponse> _authenticateProxy() { |
331 Future<HttpClientResponse> retryWithProxyCredentials(_ProxyCredentials cr) { | 331 Future<HttpClientResponse> retryWithProxyCredentials(_ProxyCredentials cr) { |
332 return fold(null, (x, y) {}).then((_) { | 332 return fold(null, (x, y) {}).then((_) { |
333 return _httpClient._openUrlFromRequest(_httpRequest.method, | 333 return _httpClient._openUrlFromRequest(_httpRequest.method, |
334 _httpRequest.uri, | 334 _httpRequest.uri, |
335 _httpRequest) | 335 _httpRequest) |
336 .then((request) => request.close()); | 336 .then((request) => request.close()); |
337 }); | 337 }); |
(...skipping 26 matching lines...) Expand all Loading... |
364 var cr = _httpClient._findProxyCredentials(proxy); | 364 var cr = _httpClient._findProxyCredentials(proxy); |
365 return retryWithProxyCredentials(cr); | 365 return retryWithProxyCredentials(cr); |
366 } else { | 366 } else { |
367 // No credentials available, complete with original response. | 367 // No credentials available, complete with original response. |
368 return this; | 368 return this; |
369 } | 369 } |
370 }); | 370 }); |
371 } | 371 } |
372 | 372 |
373 // No credentials were found and the callback was not set. | 373 // No credentials were found and the callback was not set. |
374 return new Future.immediate(this); | 374 return new Future.value(this); |
375 } | 375 } |
376 } | 376 } |
377 | 377 |
378 | 378 |
379 abstract class _HttpOutboundMessage<T> implements IOSink { | 379 abstract class _HttpOutboundMessage<T> implements IOSink { |
380 // Used to mark when the body should be written. This is used for HEAD | 380 // Used to mark when the body should be written. This is used for HEAD |
381 // requests and in error handling. | 381 // requests and in error handling. |
382 bool _ignoreBody = false; | 382 bool _ignoreBody = false; |
383 bool _headersWritten = false; | 383 bool _headersWritten = false; |
384 bool _asGZip = false; | 384 bool _asGZip = false; |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
502 // persistentConnection is not guaranteed to be in sync. | 502 // persistentConnection is not guaranteed to be in sync. |
503 if (!_headersWritten) { | 503 if (!_headersWritten) { |
504 if (!_ignoreBody && headers.contentLength == -1) { | 504 if (!_ignoreBody && headers.contentLength == -1) { |
505 // If no body was written, _ignoreBody is false (it's not a HEAD | 505 // If no body was written, _ignoreBody is false (it's not a HEAD |
506 // request) and the content-length is unspecified, set contentLength to | 506 // request) and the content-length is unspecified, set contentLength to |
507 // 0. | 507 // 0. |
508 headers.chunkedTransferEncoding = false; | 508 headers.chunkedTransferEncoding = false; |
509 headers.contentLength = 0; | 509 headers.contentLength = 0; |
510 } else if (!_ignoreBody && headers.contentLength > 0) { | 510 } else if (!_ignoreBody && headers.contentLength > 0) { |
511 _headersSink.close().catchError((_) {}); | 511 _headersSink.close().catchError((_) {}); |
512 return new Future.immediateError(new HttpException( | 512 return new Future.error(new HttpException( |
513 "No content while contentLength was specified to be greater " | 513 "No content while contentLength was specified to be greater " |
514 " than 0: ${headers.contentLength}.")); | 514 " than 0: ${headers.contentLength}.")); |
515 } | 515 } |
516 } | 516 } |
517 _writeHeaders(); | 517 _writeHeaders(); |
518 return _headersSink.close(); | 518 return _headersSink.close(); |
519 } | 519 } |
520 | 520 |
521 void _writeHeader(); // TODO(ajohnsen): Better name. | 521 void _writeHeader(); // TODO(ajohnsen): Better name. |
522 } | 522 } |
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
855 _httpClient); | 855 _httpClient); |
856 Future<HttpClientResponse> future; | 856 Future<HttpClientResponse> future; |
857 if (followRedirects && response.isRedirect) { | 857 if (followRedirects && response.isRedirect) { |
858 if (response.redirects.length < maxRedirects) { | 858 if (response.redirects.length < maxRedirects) { |
859 // Redirect and drain response. | 859 // Redirect and drain response. |
860 future = response.fold(null, (x, y) {}) | 860 future = response.fold(null, (x, y) {}) |
861 .then((_) => response.redirect()); | 861 .then((_) => response.redirect()); |
862 } else { | 862 } else { |
863 // End with exception, too many redirects. | 863 // End with exception, too many redirects. |
864 future = response.fold(null, (x, y) {}) | 864 future = response.fold(null, (x, y) {}) |
865 .then((_) => new Future.immediateError( | 865 .then((_) => new Future.error( |
866 new RedirectLimitExceededException(response.redirects))); | 866 new RedirectLimitExceededException(response.redirects))); |
867 } | 867 } |
868 } else if (response._shouldAuthenticateProxy) { | 868 } else if (response._shouldAuthenticateProxy) { |
869 future = response._authenticateProxy(); | 869 future = response._authenticateProxy(); |
870 } else if (response._shouldAuthenticate) { | 870 } else if (response._shouldAuthenticate) { |
871 future = response._authenticate(); | 871 future = response._authenticate(); |
872 } else { | 872 } else { |
873 future = new Future<HttpClientResponse>.immediate(response); | 873 future = new Future<HttpClientResponse>.value(response); |
874 } | 874 } |
875 future.then( | 875 future.then( |
876 (v) => _responseCompleter.complete(v), | 876 (v) => _responseCompleter.complete(v), |
877 onError: (e) { | 877 onError: (e) { |
878 _responseCompleter.completeError(e); | 878 _responseCompleter.completeError(e); |
879 }); | 879 }); |
880 } | 880 } |
881 | 881 |
882 void _onError(error) { | 882 void _onError(error) { |
883 _responseCompleter.completeError(error); | 883 _responseCompleter.completeError(error); |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1011 Future addStream(Stream<List<int>> stream) { | 1011 Future addStream(Stream<List<int>> stream) { |
1012 return _consumer.addStream(stream) | 1012 return _consumer.addStream(stream) |
1013 .catchError((error) { | 1013 .catchError((error) { |
1014 _doneCompleter.completeError(error); | 1014 _doneCompleter.completeError(error); |
1015 throw error; | 1015 throw error; |
1016 }); | 1016 }); |
1017 } | 1017 } |
1018 | 1018 |
1019 Future close() { | 1019 Future close() { |
1020 _doneCompleter.complete(_consumer); | 1020 _doneCompleter.complete(_consumer); |
1021 return new Future.immediate(null); | 1021 return new Future.value(); |
1022 } | 1022 } |
1023 | 1023 |
1024 Future get done => _doneCompleter.future; | 1024 Future get done => _doneCompleter.future; |
1025 } | 1025 } |
1026 | 1026 |
1027 | 1027 |
1028 class _HttpClientConnection { | 1028 class _HttpClientConnection { |
1029 final String key; | 1029 final String key; |
1030 final Socket _socket; | 1030 final Socket _socket; |
1031 final _HttpParser _httpParser; | 1031 final _HttpParser _httpParser; |
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1287 HttpClient.DEFAULT_HTTP_PORT; | 1287 HttpClient.DEFAULT_HTTP_PORT; |
1288 } | 1288 } |
1289 // Check to see if a proxy server should be used for this connection. | 1289 // Check to see if a proxy server should be used for this connection. |
1290 var proxyConf = const _ProxyConfiguration.direct(); | 1290 var proxyConf = const _ProxyConfiguration.direct(); |
1291 if (_findProxy != null) { | 1291 if (_findProxy != null) { |
1292 // TODO(sgjesse): Keep a map of these as normally only a few | 1292 // TODO(sgjesse): Keep a map of these as normally only a few |
1293 // configuration strings will be used. | 1293 // configuration strings will be used. |
1294 try { | 1294 try { |
1295 proxyConf = new _ProxyConfiguration(_findProxy(uri)); | 1295 proxyConf = new _ProxyConfiguration(_findProxy(uri)); |
1296 } catch (error, stackTrace) { | 1296 } catch (error, stackTrace) { |
1297 return new Future.immediateError(error, stackTrace); | 1297 return new Future.error(error, stackTrace); |
1298 } | 1298 } |
1299 } | 1299 } |
1300 return _getConnection(uri.domain, port, proxyConf, isSecure) | 1300 return _getConnection(uri.domain, port, proxyConf, isSecure) |
1301 .then((info) { | 1301 .then((info) { |
1302 return info.connection.send(uri, | 1302 return info.connection.send(uri, |
1303 port, | 1303 port, |
1304 method.toUpperCase(), | 1304 method.toUpperCase(), |
1305 info.proxy); | 1305 info.proxy); |
1306 }); | 1306 }); |
1307 } | 1307 } |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1353 | 1353 |
1354 // Get a new _HttpClientConnection, either from the idle pool or created from | 1354 // Get a new _HttpClientConnection, either from the idle pool or created from |
1355 // a new Socket. | 1355 // a new Socket. |
1356 Future<_ConnnectionInfo> _getConnection(String uriHost, | 1356 Future<_ConnnectionInfo> _getConnection(String uriHost, |
1357 int uriPort, | 1357 int uriPort, |
1358 _ProxyConfiguration proxyConf, | 1358 _ProxyConfiguration proxyConf, |
1359 bool isSecure) { | 1359 bool isSecure) { |
1360 Iterator<_Proxy> proxies = proxyConf.proxies.iterator; | 1360 Iterator<_Proxy> proxies = proxyConf.proxies.iterator; |
1361 | 1361 |
1362 Future<_ConnnectionInfo> connect(error) { | 1362 Future<_ConnnectionInfo> connect(error) { |
1363 if (!proxies.moveNext()) return new Future.immediateError(error); | 1363 if (!proxies.moveNext()) return new Future.error(error); |
1364 _Proxy proxy = proxies.current; | 1364 _Proxy proxy = proxies.current; |
1365 String host = proxy.isDirect ? uriHost: proxy.host; | 1365 String host = proxy.isDirect ? uriHost: proxy.host; |
1366 int port = proxy.isDirect ? uriPort: proxy.port; | 1366 int port = proxy.isDirect ? uriPort: proxy.port; |
1367 String key = isSecure ? "ssh:$host:$port" : "$host:$port"; | 1367 String key = isSecure ? "ssh:$host:$port" : "$host:$port"; |
1368 if (_idleConnections.containsKey(key)) { | 1368 if (_idleConnections.containsKey(key)) { |
1369 var connection = _idleConnections[key].first; | 1369 var connection = _idleConnections[key].first; |
1370 _idleConnections[key].remove(connection); | 1370 _idleConnections[key].remove(connection); |
1371 if (_idleConnections[key].isEmpty) { | 1371 if (_idleConnections[key].isEmpty) { |
1372 _idleConnections.remove(key); | 1372 _idleConnections.remove(key); |
1373 } | 1373 } |
1374 _activeConnections.add(connection); | 1374 _activeConnections.add(connection); |
1375 return new Future.immediate(new _ConnnectionInfo(connection, proxy)); | 1375 return new Future.value(new _ConnnectionInfo(connection, proxy)); |
1376 } | 1376 } |
1377 return (isSecure && proxy.isDirect | 1377 return (isSecure && proxy.isDirect |
1378 ? SecureSocket.connect(host, | 1378 ? SecureSocket.connect(host, |
1379 port, | 1379 port, |
1380 sendClientCertificate: true) | 1380 sendClientCertificate: true) |
1381 : Socket.connect(host, port)) | 1381 : Socket.connect(host, port)) |
1382 .then((socket) { | 1382 .then((socket) { |
1383 socket.setOption(SocketOption.TCP_NODELAY, true); | 1383 socket.setOption(SocketOption.TCP_NODELAY, true); |
1384 var connection = new _HttpClientConnection(key, socket, this); | 1384 var connection = new _HttpClientConnection(key, socket, this); |
1385 _activeConnections.add(connection); | 1385 _activeConnections.add(connection); |
(...skipping 602 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1988 | 1988 |
1989 | 1989 |
1990 class _RedirectInfo implements RedirectInfo { | 1990 class _RedirectInfo implements RedirectInfo { |
1991 const _RedirectInfo(int this.statusCode, | 1991 const _RedirectInfo(int this.statusCode, |
1992 String this.method, | 1992 String this.method, |
1993 Uri this.location); | 1993 Uri this.location); |
1994 final int statusCode; | 1994 final int statusCode; |
1995 final String method; | 1995 final String method; |
1996 final Uri location; | 1996 final Uri location; |
1997 } | 1997 } |
OLD | NEW |