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 |