| 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 1053 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1064 } | 1064 } |
| 1065 | 1065 |
| 1066 class _HttpClientConnection { | 1066 class _HttpClientConnection { |
| 1067 final String key; | 1067 final String key; |
| 1068 final Socket _socket; | 1068 final Socket _socket; |
| 1069 final bool _proxyTunnel; | 1069 final bool _proxyTunnel; |
| 1070 final _HttpParser _httpParser; | 1070 final _HttpParser _httpParser; |
| 1071 StreamSubscription _subscription; | 1071 StreamSubscription _subscription; |
| 1072 final _HttpClient _httpClient; | 1072 final _HttpClient _httpClient; |
| 1073 bool _dispose = false; | 1073 bool _dispose = false; |
| 1074 bool closed = false; |
| 1074 | 1075 |
| 1075 Completer<_HttpIncoming> _nextResponseCompleter; | 1076 Completer<_HttpIncoming> _nextResponseCompleter; |
| 1076 Future _streamFuture; | 1077 Future _streamFuture; |
| 1077 | 1078 |
| 1078 _HttpClientConnection(String this.key, | 1079 _HttpClientConnection(String this.key, |
| 1079 Socket this._socket, | 1080 Socket this._socket, |
| 1080 _HttpClient this._httpClient, | 1081 _HttpClient this._httpClient, |
| 1081 [this._proxyTunnel = false]) | 1082 [this._proxyTunnel = false]) |
| 1082 : _httpParser = new _HttpParser.responseParser() { | 1083 : _httpParser = new _HttpParser.responseParser() { |
| 1083 _socket.pipe(_httpParser); | 1084 _socket.pipe(_httpParser); |
| 1084 | 1085 |
| 1085 // Set up handlers on the parser here, so we are sure to get 'onDone' from | 1086 // Set up handlers on the parser here, so we are sure to get 'onDone' from |
| 1086 // the parser. | 1087 // the parser. |
| 1087 _subscription = _httpParser.listen( | 1088 _subscription = _httpParser.listen( |
| 1088 (incoming) { | 1089 (incoming) { |
| 1089 // Only handle one incoming response at the time. Keep the | 1090 // Only handle one incoming response at the time. Keep the |
| 1090 // stream paused until the response have been processed. | 1091 // stream paused until the response have been processed. |
| 1091 _subscription.pause(); | 1092 _subscription.pause(); |
| 1092 // We assume the response is not here, until we have send the request. | 1093 // We assume the response is not here, until we have send the request. |
| 1093 assert(_nextResponseCompleter != null); | 1094 if (_nextResponseCompleter == null) { |
| 1094 var completer = _nextResponseCompleter; | 1095 throw new HttpException("Unexpected response."); |
| 1096 } |
| 1097 _nextResponseCompleter.complete(incoming); |
| 1095 _nextResponseCompleter = null; | 1098 _nextResponseCompleter = null; |
| 1096 completer.complete(incoming); | |
| 1097 }, | 1099 }, |
| 1098 onError: (error) { | 1100 onError: (error) { |
| 1099 if (_nextResponseCompleter != null) { | 1101 if (_nextResponseCompleter != null) { |
| 1100 _nextResponseCompleter.completeError(error); | 1102 _nextResponseCompleter.completeError(error); |
| 1101 _nextResponseCompleter = null; | 1103 _nextResponseCompleter = null; |
| 1102 } | 1104 } |
| 1103 }, | 1105 }, |
| 1104 onDone: () { | 1106 onDone: () { |
| 1107 if (_nextResponseCompleter != null) { |
| 1108 _nextResponseCompleter.completeError(new HttpException( |
| 1109 "Connection closed before response was received")); |
| 1110 _nextResponseCompleter = null; |
| 1111 } |
| 1105 close(); | 1112 close(); |
| 1106 }); | 1113 }); |
| 1107 } | 1114 } |
| 1108 | 1115 |
| 1109 _HttpClientRequest send(Uri uri, int port, String method, _Proxy proxy) { | 1116 _HttpClientRequest send(Uri uri, int port, String method, _Proxy proxy) { |
| 1117 if (closed) { |
| 1118 throw new HttpException("Socket closed before request was sent"); |
| 1119 } |
| 1110 // Start with pausing the parser. | 1120 // Start with pausing the parser. |
| 1111 _subscription.pause(); | 1121 _subscription.pause(); |
| 1112 _ProxyCredentials proxyCreds; // Credentials used to authorize proxy. | 1122 _ProxyCredentials proxyCreds; // Credentials used to authorize proxy. |
| 1113 _SiteCredentials creds; // Credentials used to authorize this request. | 1123 _SiteCredentials creds; // Credentials used to authorize this request. |
| 1114 var outgoing = new _HttpOutgoing(_socket); | 1124 var outgoing = new _HttpOutgoing(_socket); |
| 1115 // Create new request object, wrapping the outgoing connection. | 1125 // Create new request object, wrapping the outgoing connection. |
| 1116 var request = new _HttpClientRequest(outgoing, | 1126 var request = new _HttpClientRequest(outgoing, |
| 1117 uri, | 1127 uri, |
| 1118 method, | 1128 method, |
| 1119 proxy, | 1129 proxy, |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1220 }); | 1230 }); |
| 1221 return request; | 1231 return request; |
| 1222 } | 1232 } |
| 1223 | 1233 |
| 1224 Future<Socket> detachSocket() { | 1234 Future<Socket> detachSocket() { |
| 1225 return _streamFuture.then( | 1235 return _streamFuture.then( |
| 1226 (_) => new _DetachedSocket(_socket, _httpParser.detachIncoming())); | 1236 (_) => new _DetachedSocket(_socket, _httpParser.detachIncoming())); |
| 1227 } | 1237 } |
| 1228 | 1238 |
| 1229 void destroy() { | 1239 void destroy() { |
| 1240 closed = true; |
| 1230 _httpClient._connectionClosed(this); | 1241 _httpClient._connectionClosed(this); |
| 1231 _socket.destroy(); | 1242 _socket.destroy(); |
| 1232 } | 1243 } |
| 1233 | 1244 |
| 1234 void close() { | 1245 void close() { |
| 1246 closed = true; |
| 1235 _httpClient._connectionClosed(this); | 1247 _httpClient._connectionClosed(this); |
| 1236 _streamFuture | 1248 _streamFuture |
| 1237 // TODO(ajohnsen): Add timeout. | 1249 // TODO(ajohnsen): Add timeout. |
| 1238 .then((_) => _socket.destroy()); | 1250 .then((_) => _socket.destroy()); |
| 1239 } | 1251 } |
| 1240 | 1252 |
| 1241 Future<_HttpClientConnection> createProxyTunnel(host, port, proxy) { | 1253 Future<_HttpClientConnection> createProxyTunnel(host, port, proxy) { |
| 1242 _HttpClientRequest request = | 1254 _HttpClientRequest request = |
| 1243 send(new Uri.fromComponents(domain: host, port: port), | 1255 send(new Uri.fromComponents(domain: host, port: port), |
| 1244 port, | 1256 port, |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1400 // TODO(sgjesse): Keep a map of these as normally only a few | 1412 // TODO(sgjesse): Keep a map of these as normally only a few |
| 1401 // configuration strings will be used. | 1413 // configuration strings will be used. |
| 1402 try { | 1414 try { |
| 1403 proxyConf = new _ProxyConfiguration(_findProxy(uri)); | 1415 proxyConf = new _ProxyConfiguration(_findProxy(uri)); |
| 1404 } catch (error, stackTrace) { | 1416 } catch (error, stackTrace) { |
| 1405 return new Future.error(error, stackTrace); | 1417 return new Future.error(error, stackTrace); |
| 1406 } | 1418 } |
| 1407 } | 1419 } |
| 1408 return _getConnection(uri.domain, port, proxyConf, isSecure) | 1420 return _getConnection(uri.domain, port, proxyConf, isSecure) |
| 1409 .then((info) { | 1421 .then((info) { |
| 1410 return info.connection.send(uri, | 1422 send(info) { |
| 1411 port, | 1423 return info.connection.send(uri, |
| 1412 method.toUpperCase(), | 1424 port, |
| 1413 info.proxy); | 1425 method.toUpperCase(), |
| 1426 info.proxy); |
| 1427 } |
| 1428 // If the connection was closed before the request was sent, create |
| 1429 // and use another connection. |
| 1430 if (info.connection.closed) { |
| 1431 return _getConnection(uri.domain, port, proxyConf, isSecure) |
| 1432 .then(send); |
| 1433 } |
| 1434 return send(info); |
| 1414 }); | 1435 }); |
| 1415 } | 1436 } |
| 1416 | 1437 |
| 1417 Future<HttpClientRequest> _openUrlFromRequest(String method, | 1438 Future<HttpClientRequest> _openUrlFromRequest(String method, |
| 1418 Uri uri, | 1439 Uri uri, |
| 1419 _HttpClientRequest previous) { | 1440 _HttpClientRequest previous) { |
| 1420 // If the new URI is relative (to either '/' or some sub-path), | 1441 // If the new URI is relative (to either '/' or some sub-path), |
| 1421 // construct a full URI from the previous one. | 1442 // construct a full URI from the previous one. |
| 1422 // See http://tools.ietf.org/html/rfc3986#section-4.2 | 1443 // See http://tools.ietf.org/html/rfc3986#section-4.2 |
| 1423 replaceComponents({scheme, domain, port, path}) { | 1444 replaceComponents({scheme, domain, port, path}) { |
| (...skipping 811 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2235 | 2256 |
| 2236 | 2257 |
| 2237 class _RedirectInfo implements RedirectInfo { | 2258 class _RedirectInfo implements RedirectInfo { |
| 2238 const _RedirectInfo(int this.statusCode, | 2259 const _RedirectInfo(int this.statusCode, |
| 2239 String this.method, | 2260 String this.method, |
| 2240 Uri this.location); | 2261 Uri this.location); |
| 2241 final int statusCode; | 2262 final int statusCode; |
| 2242 final String method; | 2263 final String method; |
| 2243 final Uri location; | 2264 final Uri location; |
| 2244 } | 2265 } |
| OLD | NEW |