| 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 23 matching lines...) Expand all Loading... |
| 34 _HttpIncoming(_HttpHeaders this.headers, | 34 _HttpIncoming(_HttpHeaders this.headers, |
| 35 int this._transferLength, | 35 int this._transferLength, |
| 36 Stream<List<int>> this._stream) { | 36 Stream<List<int>> this._stream) { |
| 37 } | 37 } |
| 38 | 38 |
| 39 StreamSubscription<List<int>> listen(void onData(List<int> event), | 39 StreamSubscription<List<int>> listen(void onData(List<int> event), |
| 40 {void onError(error), | 40 {void onError(error), |
| 41 void onDone(), | 41 void onDone(), |
| 42 bool cancelOnError}) { | 42 bool cancelOnError}) { |
| 43 hasSubscriber = true; | 43 hasSubscriber = true; |
| 44 return _stream.listen(onData, | 44 return _stream |
| 45 onError: onError, | 45 .handleError((error) { |
| 46 onDone: onDone, | 46 throw new HttpException(error.message, uri: uri); |
| 47 cancelOnError: cancelOnError); | 47 }) |
| 48 .listen(onData, |
| 49 onError: onError, |
| 50 onDone: onDone, |
| 51 cancelOnError: cancelOnError); |
| 48 } | 52 } |
| 49 | 53 |
| 50 // Is completed once all data have been received. | 54 // Is completed once all data have been received. |
| 51 Future get dataDone => _dataCompleter.future; | 55 Future get dataDone => _dataCompleter.future; |
| 52 | 56 |
| 53 void close(bool closing) { | 57 void close(bool closing) { |
| 54 fullBodyRead = true; | 58 fullBodyRead = true; |
| 55 hasSubscriber = true; | 59 hasSubscriber = true; |
| 56 _dataCompleter.complete(closing); | 60 _dataCompleter.complete(closing); |
| 57 } | 61 } |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 153 final _HttpClient _httpClient; | 157 final _HttpClient _httpClient; |
| 154 | 158 |
| 155 // The HttpClientRequest of this response. | 159 // The HttpClientRequest of this response. |
| 156 final _HttpClientRequest _httpRequest; | 160 final _HttpClientRequest _httpRequest; |
| 157 | 161 |
| 158 List<Cookie> _cookies; | 162 List<Cookie> _cookies; |
| 159 | 163 |
| 160 _HttpClientResponse(_HttpIncoming _incoming, | 164 _HttpClientResponse(_HttpIncoming _incoming, |
| 161 _HttpClientRequest this._httpRequest, | 165 _HttpClientRequest this._httpRequest, |
| 162 _HttpClient this._httpClient) | 166 _HttpClient this._httpClient) |
| 163 : super(_incoming); | 167 : super(_incoming) { |
| 168 // Set uri for potential exceptions. |
| 169 _incoming.uri = _httpRequest.uri; |
| 170 } |
| 164 | 171 |
| 165 int get statusCode => _incoming.statusCode; | 172 int get statusCode => _incoming.statusCode; |
| 166 String get reasonPhrase => _incoming.reasonPhrase; | 173 String get reasonPhrase => _incoming.reasonPhrase; |
| 167 | 174 |
| 168 X509Certificate get certificate { | 175 X509Certificate get certificate { |
| 169 var socket = _httpRequest._httpClientConnection._socket; | 176 var socket = _httpRequest._httpClientConnection._socket; |
| 170 return socket.peerCertificate; | 177 return socket.peerCertificate; |
| 171 } | 178 } |
| 172 | 179 |
| 173 List<Cookie> get cookies { | 180 List<Cookie> get cookies { |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 388 // Used to mark when the body should be written. This is used for HEAD | 395 // Used to mark when the body should be written. This is used for HEAD |
| 389 // requests and in error handling. | 396 // requests and in error handling. |
| 390 bool _ignoreBody = false; | 397 bool _ignoreBody = false; |
| 391 bool _headersWritten = false; | 398 bool _headersWritten = false; |
| 392 bool _asGZip = false; | 399 bool _asGZip = false; |
| 393 | 400 |
| 394 IOSink _headersSink; | 401 IOSink _headersSink; |
| 395 IOSink _dataSink; | 402 IOSink _dataSink; |
| 396 | 403 |
| 397 final _HttpOutgoing _outgoing; | 404 final _HttpOutgoing _outgoing; |
| 405 final Uri _uri; |
| 398 | 406 |
| 399 final _HttpHeaders headers; | 407 final _HttpHeaders headers; |
| 400 | 408 |
| 401 _HttpOutboundMessage(String protocolVersion, _HttpOutgoing outgoing) | 409 _HttpOutboundMessage(Uri this._uri, |
| 410 String protocolVersion, |
| 411 _HttpOutgoing outgoing) |
| 402 : _outgoing = outgoing, | 412 : _outgoing = outgoing, |
| 403 _headersSink = new IOSink(outgoing, encoding: Encoding.ASCII), | 413 _headersSink = new IOSink(outgoing, encoding: Encoding.ASCII), |
| 404 headers = new _HttpHeaders(protocolVersion) { | 414 headers = new _HttpHeaders(protocolVersion) { |
| 405 _dataSink = new IOSink(new _HttpOutboundConsumer(this)); | 415 _dataSink = new IOSink(new _HttpOutboundConsumer(this)); |
| 406 } | 416 } |
| 407 | 417 |
| 408 int get contentLength => headers.contentLength; | 418 int get contentLength => headers.contentLength; |
| 409 void set contentLength(int contentLength) { | 419 void set contentLength(int contentLength) { |
| 410 headers.contentLength = contentLength; | 420 headers.contentLength = contentLength; |
| 411 } | 421 } |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 504 return _headersSink.close(); | 514 return _headersSink.close(); |
| 505 } | 515 } |
| 506 stream = stream.transform(new _BufferTransformer()); | 516 stream = stream.transform(new _BufferTransformer()); |
| 507 if (headers.chunkedTransferEncoding) { | 517 if (headers.chunkedTransferEncoding) { |
| 508 if (_asGZip) { | 518 if (_asGZip) { |
| 509 stream = stream.transform(new ZLibDeflater(gzip: true, level: 6)); | 519 stream = stream.transform(new ZLibDeflater(gzip: true, level: 6)); |
| 510 } | 520 } |
| 511 stream = stream.transform(new _ChunkedTransformer()); | 521 stream = stream.transform(new _ChunkedTransformer()); |
| 512 } else if (contentLength >= 0) { | 522 } else if (contentLength >= 0) { |
| 513 stream = stream.transform( | 523 stream = stream.transform( |
| 514 new _ContentLengthValidator(contentLength)); | 524 new _ContentLengthValidator(contentLength, _uri)); |
| 515 } | 525 } |
| 516 return _headersSink.addStream(stream); | 526 return _headersSink.addStream(stream); |
| 517 }); | 527 }); |
| 518 } | 528 } |
| 519 | 529 |
| 520 Future _close() { | 530 Future _close() { |
| 521 // TODO(ajohnsen): Currently, contentLength, chunkedTransferEncoding and | 531 // TODO(ajohnsen): Currently, contentLength, chunkedTransferEncoding and |
| 522 // persistentConnection is not guaranteed to be in sync. | 532 // persistentConnection is not guaranteed to be in sync. |
| 523 if (!_headersWritten) { | 533 if (!_headersWritten) { |
| 524 if (!_ignoreBody && headers.contentLength == -1) { | 534 if (!_ignoreBody && headers.contentLength == -1) { |
| 525 // If no body was written, _ignoreBody is false (it's not a HEAD | 535 // If no body was written, _ignoreBody is false (it's not a HEAD |
| 526 // request) and the content-length is unspecified, set contentLength to | 536 // request) and the content-length is unspecified, set contentLength to |
| 527 // 0. | 537 // 0. |
| 528 headers.chunkedTransferEncoding = false; | 538 headers.chunkedTransferEncoding = false; |
| 529 headers.contentLength = 0; | 539 headers.contentLength = 0; |
| 530 } else if (!_ignoreBody && headers.contentLength > 0) { | 540 } else if (!_ignoreBody && headers.contentLength > 0) { |
| 531 _headersSink.close().catchError((_) {}); | 541 _headersSink.close().catchError((_) {}); |
| 532 return new Future.error(new HttpException( | 542 return new Future.error(new HttpException( |
| 533 "No content while contentLength was specified to be greater " | 543 "No content while contentLength was specified to be greater " |
| 534 " than 0: ${headers.contentLength}.")); | 544 " than 0: ${headers.contentLength}.", |
| 545 uri: _uri)); |
| 535 } | 546 } |
| 536 } | 547 } |
| 537 return _writeHeaders().then((_) => _headersSink.close()); | 548 return _writeHeaders().then((_) => _headersSink.close()); |
| 538 } | 549 } |
| 539 | 550 |
| 540 void _writeHeader(); // TODO(ajohnsen): Better name. | 551 void _writeHeader(); // TODO(ajohnsen): Better name. |
| 541 } | 552 } |
| 542 | 553 |
| 543 | 554 |
| 544 class _HttpOutboundConsumer implements StreamConsumer { | 555 class _HttpOutboundConsumer implements StreamConsumer { |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 669 } | 680 } |
| 670 | 681 |
| 671 | 682 |
| 672 class _HttpResponse extends _HttpOutboundMessage<HttpResponse> | 683 class _HttpResponse extends _HttpOutboundMessage<HttpResponse> |
| 673 implements HttpResponse { | 684 implements HttpResponse { |
| 674 int statusCode = 200; | 685 int statusCode = 200; |
| 675 String _reasonPhrase; | 686 String _reasonPhrase; |
| 676 List<Cookie> _cookies; | 687 List<Cookie> _cookies; |
| 677 _HttpRequest _httpRequest; | 688 _HttpRequest _httpRequest; |
| 678 | 689 |
| 679 _HttpResponse(String protocolVersion, | 690 _HttpResponse(Uri uri, |
| 691 String protocolVersion, |
| 680 _HttpOutgoing _outgoing, | 692 _HttpOutgoing _outgoing, |
| 681 String serverHeader) | 693 String serverHeader) |
| 682 : super(protocolVersion, _outgoing) { | 694 : super(uri, protocolVersion, _outgoing) { |
| 683 if (serverHeader != null) headers.set('Server', serverHeader); | 695 if (serverHeader != null) headers.set('Server', serverHeader); |
| 684 } | 696 } |
| 685 | 697 |
| 686 List<Cookie> get cookies { | 698 List<Cookie> get cookies { |
| 687 if (_cookies == null) _cookies = new List<Cookie>(); | 699 if (_cookies == null) _cookies = new List<Cookie>(); |
| 688 return _cookies; | 700 return _cookies; |
| 689 } | 701 } |
| 690 | 702 |
| 691 String get reasonPhrase => _findReasonPhrase(statusCode); | 703 String get reasonPhrase => _findReasonPhrase(statusCode); |
| 692 void set reasonPhrase(String reasonPhrase) { | 704 void set reasonPhrase(String reasonPhrase) { |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 837 Future<HttpClientResponse> _response; | 849 Future<HttpClientResponse> _response; |
| 838 | 850 |
| 839 // TODO(ajohnsen): Get default value from client? | 851 // TODO(ajohnsen): Get default value from client? |
| 840 bool _followRedirects = true; | 852 bool _followRedirects = true; |
| 841 | 853 |
| 842 int _maxRedirects = 5; | 854 int _maxRedirects = 5; |
| 843 | 855 |
| 844 List<RedirectInfo> _responseRedirects = []; | 856 List<RedirectInfo> _responseRedirects = []; |
| 845 | 857 |
| 846 _HttpClientRequest(_HttpOutgoing outgoing, | 858 _HttpClientRequest(_HttpOutgoing outgoing, |
| 847 Uri this.uri, | 859 Uri uri, |
| 848 String this.method, | 860 String this.method, |
| 849 _Proxy this._proxy, | 861 _Proxy this._proxy, |
| 850 _HttpClient this._httpClient, | 862 _HttpClient this._httpClient, |
| 851 _HttpClientConnection this._httpClientConnection) | 863 _HttpClientConnection this._httpClientConnection) |
| 852 : super("1.1", outgoing) { | 864 : super(uri, "1.1", outgoing), |
| 865 uri = uri { |
| 853 // GET and HEAD have 'content-length: 0' by default. | 866 // GET and HEAD have 'content-length: 0' by default. |
| 854 if (method == "GET" || method == "HEAD") { | 867 if (method == "GET" || method == "HEAD") { |
| 855 contentLength = 0; | 868 contentLength = 0; |
| 856 } | 869 } |
| 857 } | 870 } |
| 858 | 871 |
| 859 Future<HttpClientResponse> get done { | 872 Future<HttpClientResponse> get done { |
| 860 if (_response == null) { | 873 if (_response == null) { |
| 861 _response = Future.wait([_responseCompleter.future, | 874 _response = Future.wait([_responseCompleter.future, |
| 862 super.done]) | 875 super.done]) |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1042 | 1055 |
| 1043 static List<int> get _chunk0Length => new Uint8List.fromList( | 1056 static List<int> get _chunk0Length => new Uint8List.fromList( |
| 1044 const [0x30, _CharCode.CR, _CharCode.LF, _CharCode.CR, _CharCode.LF]); | 1057 const [0x30, _CharCode.CR, _CharCode.LF, _CharCode.CR, _CharCode.LF]); |
| 1045 } | 1058 } |
| 1046 | 1059 |
| 1047 | 1060 |
| 1048 // Transformer that validates the content length. | 1061 // Transformer that validates the content length. |
| 1049 class _ContentLengthValidator | 1062 class _ContentLengthValidator |
| 1050 extends StreamEventTransformer<List<int>, List<int>> { | 1063 extends StreamEventTransformer<List<int>, List<int>> { |
| 1051 final int expectedContentLength; | 1064 final int expectedContentLength; |
| 1065 final Uri uri; |
| 1052 int _bytesWritten = 0; | 1066 int _bytesWritten = 0; |
| 1053 | 1067 |
| 1054 _ContentLengthValidator(int this.expectedContentLength); | 1068 _ContentLengthValidator(int this.expectedContentLength, Uri this.uri); |
| 1055 | 1069 |
| 1056 void handleData(List<int> data, EventSink<List<int>> sink) { | 1070 void handleData(List<int> data, EventSink<List<int>> sink) { |
| 1057 _bytesWritten += data.length; | 1071 _bytesWritten += data.length; |
| 1058 if (_bytesWritten > expectedContentLength) { | 1072 if (_bytesWritten > expectedContentLength) { |
| 1059 sink.addError(new HttpException( | 1073 sink.addError(new HttpException( |
| 1060 "Content size exceeds specified contentLength. " | 1074 "Content size exceeds specified contentLength. " |
| 1061 "$_bytesWritten bytes written while expected " | 1075 "$_bytesWritten bytes written while expected " |
| 1062 "$expectedContentLength. " | 1076 "$expectedContentLength. " |
| 1063 "[${new String.fromCharCodes(data)}]")); | 1077 "[${new String.fromCharCodes(data)}]", |
| 1078 uri: uri)); |
| 1064 sink.close(); | 1079 sink.close(); |
| 1065 } else { | 1080 } else { |
| 1066 sink.add(data); | 1081 sink.add(data); |
| 1067 } | 1082 } |
| 1068 } | 1083 } |
| 1069 | 1084 |
| 1070 void handleDone(EventSink<List<int>> sink) { | 1085 void handleDone(EventSink<List<int>> sink) { |
| 1071 if (_bytesWritten < expectedContentLength) { | 1086 if (_bytesWritten < expectedContentLength) { |
| 1072 sink.addError(new HttpException( | 1087 sink.addError(new HttpException( |
| 1073 "Content size below specified contentLength. " | 1088 "Content size below specified contentLength. " |
| 1074 " $_bytesWritten bytes written while expected " | 1089 " $_bytesWritten bytes written while expected " |
| 1075 "$expectedContentLength.")); | 1090 "$expectedContentLength.", |
| 1091 uri: uri)); |
| 1076 } | 1092 } |
| 1077 sink.close(); | 1093 sink.close(); |
| 1078 } | 1094 } |
| 1079 } | 1095 } |
| 1080 | 1096 |
| 1081 | 1097 |
| 1082 // Extends StreamConsumer as this is an internal type, only used to pipe to. | 1098 // Extends StreamConsumer as this is an internal type, only used to pipe to. |
| 1083 class _HttpOutgoing implements StreamConsumer<List<int>> { | 1099 class _HttpOutgoing implements StreamConsumer<List<int>> { |
| 1084 final Completer _doneCompleter = new Completer(); | 1100 final Completer _doneCompleter = new Completer(); |
| 1085 final StreamConsumer _consumer; | 1101 final StreamConsumer _consumer; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1105 class _HttpClientConnection { | 1121 class _HttpClientConnection { |
| 1106 final String key; | 1122 final String key; |
| 1107 final Socket _socket; | 1123 final Socket _socket; |
| 1108 final bool _proxyTunnel; | 1124 final bool _proxyTunnel; |
| 1109 final _HttpParser _httpParser; | 1125 final _HttpParser _httpParser; |
| 1110 StreamSubscription _subscription; | 1126 StreamSubscription _subscription; |
| 1111 final _HttpClient _httpClient; | 1127 final _HttpClient _httpClient; |
| 1112 bool _dispose = false; | 1128 bool _dispose = false; |
| 1113 Timer _idleTimer; | 1129 Timer _idleTimer; |
| 1114 bool closed = false; | 1130 bool closed = false; |
| 1131 Uri _currentUri; |
| 1115 | 1132 |
| 1116 Completer<_HttpIncoming> _nextResponseCompleter; | 1133 Completer<_HttpIncoming> _nextResponseCompleter; |
| 1117 Future _streamFuture; | 1134 Future _streamFuture; |
| 1118 | 1135 |
| 1119 _HttpClientConnection(String this.key, | 1136 _HttpClientConnection(String this.key, |
| 1120 Socket this._socket, | 1137 Socket this._socket, |
| 1121 _HttpClient this._httpClient, | 1138 _HttpClient this._httpClient, |
| 1122 [this._proxyTunnel = false]) | 1139 [this._proxyTunnel = false]) |
| 1123 : _httpParser = new _HttpParser.responseParser() { | 1140 : _httpParser = new _HttpParser.responseParser() { |
| 1124 _socket.pipe(_httpParser); | 1141 _socket.pipe(_httpParser); |
| 1125 | 1142 |
| 1126 // Set up handlers on the parser here, so we are sure to get 'onDone' from | 1143 // Set up handlers on the parser here, so we are sure to get 'onDone' from |
| 1127 // the parser. | 1144 // the parser. |
| 1128 _subscription = _httpParser.listen( | 1145 _subscription = _httpParser.listen( |
| 1129 (incoming) { | 1146 (incoming) { |
| 1130 // Only handle one incoming response at the time. Keep the | 1147 // Only handle one incoming response at the time. Keep the |
| 1131 // stream paused until the response have been processed. | 1148 // stream paused until the response have been processed. |
| 1132 _subscription.pause(); | 1149 _subscription.pause(); |
| 1133 // We assume the response is not here, until we have send the request. | 1150 // We assume the response is not here, until we have send the request. |
| 1134 if (_nextResponseCompleter == null) { | 1151 if (_nextResponseCompleter == null) { |
| 1135 throw new HttpException("Unexpected response."); | 1152 throw new HttpException("Unexpected response.", uri: _currentUri); |
| 1136 } | 1153 } |
| 1137 _nextResponseCompleter.complete(incoming); | 1154 _nextResponseCompleter.complete(incoming); |
| 1138 _nextResponseCompleter = null; | 1155 _nextResponseCompleter = null; |
| 1139 }, | 1156 }, |
| 1140 onError: (error) { | 1157 onError: (error) { |
| 1141 if (_nextResponseCompleter != null) { | 1158 if (_nextResponseCompleter != null) { |
| 1142 _nextResponseCompleter.completeError(error); | 1159 _nextResponseCompleter.completeError( |
| 1160 new HttpException(error.message, uri: _currentUri)); |
| 1143 _nextResponseCompleter = null; | 1161 _nextResponseCompleter = null; |
| 1144 } | 1162 } |
| 1145 }, | 1163 }, |
| 1146 onDone: () { | 1164 onDone: () { |
| 1147 if (_nextResponseCompleter != null) { | 1165 if (_nextResponseCompleter != null) { |
| 1148 _nextResponseCompleter.completeError(new HttpException( | 1166 _nextResponseCompleter.completeError(new HttpException( |
| 1149 "Connection closed before response was received")); | 1167 "Connection closed before response was received", |
| 1168 uri: _currentUri)); |
| 1150 _nextResponseCompleter = null; | 1169 _nextResponseCompleter = null; |
| 1151 } | 1170 } |
| 1152 close(); | 1171 close(); |
| 1153 }); | 1172 }); |
| 1154 } | 1173 } |
| 1155 | 1174 |
| 1156 _HttpClientRequest send(Uri uri, int port, String method, _Proxy proxy) { | 1175 _HttpClientRequest send(Uri uri, int port, String method, _Proxy proxy) { |
| 1157 if (closed) { | 1176 if (closed) { |
| 1158 throw new HttpException("Socket closed before request was sent"); | 1177 throw new HttpException( |
| 1178 "Socket closed before request was sent", uri: uri); |
| 1159 } | 1179 } |
| 1180 _currentUri = uri; |
| 1160 // Start with pausing the parser. | 1181 // Start with pausing the parser. |
| 1161 _subscription.pause(); | 1182 _subscription.pause(); |
| 1162 _ProxyCredentials proxyCreds; // Credentials used to authorize proxy. | 1183 _ProxyCredentials proxyCreds; // Credentials used to authorize proxy. |
| 1163 _SiteCredentials creds; // Credentials used to authorize this request. | 1184 _SiteCredentials creds; // Credentials used to authorize this request. |
| 1164 var outgoing = new _HttpOutgoing(_socket); | 1185 var outgoing = new _HttpOutgoing(_socket); |
| 1165 // Create new request object, wrapping the outgoing connection. | 1186 // Create new request object, wrapping the outgoing connection. |
| 1166 var request = new _HttpClientRequest(outgoing, | 1187 var request = new _HttpClientRequest(outgoing, |
| 1167 uri, | 1188 uri, |
| 1168 method, | 1189 method, |
| 1169 proxy, | 1190 proxy, |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1204 // data). | 1225 // data). |
| 1205 _httpParser.responseToMethod = method; | 1226 _httpParser.responseToMethod = method; |
| 1206 _streamFuture = outgoing.done | 1227 _streamFuture = outgoing.done |
| 1207 .then((s) { | 1228 .then((s) { |
| 1208 // Request sent, set up response completer. | 1229 // Request sent, set up response completer. |
| 1209 _nextResponseCompleter = new Completer(); | 1230 _nextResponseCompleter = new Completer(); |
| 1210 | 1231 |
| 1211 // Listen for response. | 1232 // Listen for response. |
| 1212 _nextResponseCompleter.future | 1233 _nextResponseCompleter.future |
| 1213 .then((incoming) { | 1234 .then((incoming) { |
| 1235 _currentUri = null; |
| 1214 incoming.dataDone.then((_) { | 1236 incoming.dataDone.then((_) { |
| 1215 if (!_dispose && | 1237 if (!_dispose && |
| 1216 incoming.headers.persistentConnection && | 1238 incoming.headers.persistentConnection && |
| 1217 request.persistentConnection) { | 1239 request.persistentConnection) { |
| 1218 // Return connection, now we are done. | 1240 // Return connection, now we are done. |
| 1219 _httpClient._returnConnection(this); | 1241 _httpClient._returnConnection(this); |
| 1220 _subscription.resume(); | 1242 _subscription.resume(); |
| 1221 } else { | 1243 } else { |
| 1222 destroy(); | 1244 destroy(); |
| 1223 } | 1245 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1248 var nextnonce = header.parameters["nextnonce"]; | 1270 var nextnonce = header.parameters["nextnonce"]; |
| 1249 if (nextnonce != null) creds.nonce = nextnonce; | 1271 if (nextnonce != null) creds.nonce = nextnonce; |
| 1250 } | 1272 } |
| 1251 } | 1273 } |
| 1252 request._onIncoming(incoming); | 1274 request._onIncoming(incoming); |
| 1253 }) | 1275 }) |
| 1254 // If we see a state error, we failed to get the 'first' | 1276 // If we see a state error, we failed to get the 'first' |
| 1255 // element. | 1277 // element. |
| 1256 .catchError((error) { | 1278 .catchError((error) { |
| 1257 throw new HttpException( | 1279 throw new HttpException( |
| 1258 "Connection closed before data was received"); | 1280 "Connection closed before data was received", uri); |
| 1259 }, test: (error) => error is StateError) | 1281 }, test: (error) => error is StateError) |
| 1260 .catchError((error) { | 1282 .catchError((error) { |
| 1261 // We are done with the socket. | 1283 // We are done with the socket. |
| 1262 destroy(); | 1284 destroy(); |
| 1263 request._onError(error); | 1285 request._onError(error); |
| 1264 }); | 1286 }); |
| 1265 | 1287 |
| 1266 // Resume the parser now we have a handler. | 1288 // Resume the parser now we have a handler. |
| 1267 _subscription.resume(); | 1289 _subscription.resume(); |
| 1268 return s; | 1290 return s; |
| (...skipping 507 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1776 (incoming) { | 1798 (incoming) { |
| 1777 // If the incoming was closed, close the connection. | 1799 // If the incoming was closed, close the connection. |
| 1778 incoming.dataDone.then((closing) { | 1800 incoming.dataDone.then((closing) { |
| 1779 if (closing) destroy(); | 1801 if (closing) destroy(); |
| 1780 }); | 1802 }); |
| 1781 // Only handle one incoming request at the time. Keep the | 1803 // Only handle one incoming request at the time. Keep the |
| 1782 // stream paused until the request has been send. | 1804 // stream paused until the request has been send. |
| 1783 _subscription.pause(); | 1805 _subscription.pause(); |
| 1784 _state = _ACTIVE; | 1806 _state = _ACTIVE; |
| 1785 var outgoing = new _HttpOutgoing(_socket); | 1807 var outgoing = new _HttpOutgoing(_socket); |
| 1786 var response = new _HttpResponse(incoming.headers.protocolVersion, | 1808 var response = new _HttpResponse(incoming.uri, |
| 1809 incoming.headers.protocolVersion, |
| 1787 outgoing, | 1810 outgoing, |
| 1788 _httpServer.serverHeader); | 1811 _httpServer.serverHeader); |
| 1789 var request = new _HttpRequest(response, incoming, _httpServer, this); | 1812 var request = new _HttpRequest(response, incoming, _httpServer, this); |
| 1790 _streamFuture = outgoing.done | 1813 _streamFuture = outgoing.done |
| 1791 .then((_) { | 1814 .then((_) { |
| 1792 if (_state == _DETACHED) return; | 1815 if (_state == _DETACHED) return; |
| 1793 if (response.persistentConnection && | 1816 if (response.persistentConnection && |
| 1794 request.persistentConnection && | 1817 request.persistentConnection && |
| 1795 incoming.fullBodyRead) { | 1818 incoming.fullBodyRead) { |
| 1796 _state = _IDLE; | 1819 _state = _IDLE; |
| (...skipping 584 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2381 final Uri location; | 2404 final Uri location; |
| 2382 } | 2405 } |
| 2383 | 2406 |
| 2384 String _getHttpVersion() { | 2407 String _getHttpVersion() { |
| 2385 var version = Platform.version; | 2408 var version = Platform.version; |
| 2386 // Only include major and minor version numbers. | 2409 // Only include major and minor version numbers. |
| 2387 int index = version.indexOf('.', version.indexOf('.') + 1); | 2410 int index = version.indexOf('.', version.indexOf('.') + 1); |
| 2388 version = version.substring(0, index); | 2411 version = version.substring(0, index); |
| 2389 return 'Dart/$version (dart:io)'; | 2412 return 'Dart/$version (dart:io)'; |
| 2390 } | 2413 } |
| OLD | NEW |