Chromium Code Reviews| 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 330 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 | 392 // Used to mark when the body should be written. This is used for HEAD |
| 389 // requests and in error handling. | 393 // requests and in error handling. |
| 390 bool _ignoreBody = false; | 394 bool _ignoreBody = false; |
| 391 bool _headersWritten = false; | 395 bool _headersWritten = false; |
| 392 bool _asGZip = false; | 396 bool _asGZip = false; |
| 393 | 397 |
| 394 IOSink _headersSink; | 398 IOSink _headersSink; |
| 395 IOSink _dataSink; | 399 IOSink _dataSink; |
| 396 | 400 |
| 397 final _HttpOutgoing _outgoing; | 401 final _HttpOutgoing _outgoing; |
| 402 final Uri _uri; | |
| 398 | 403 |
| 399 final _HttpHeaders headers; | 404 final _HttpHeaders headers; |
| 400 | 405 |
| 401 _HttpOutboundMessage(String protocolVersion, _HttpOutgoing outgoing) | 406 _HttpOutboundMessage(Uri this._uri, |
| 407 String protocolVersion, | |
| 408 _HttpOutgoing outgoing) | |
| 402 : _outgoing = outgoing, | 409 : _outgoing = outgoing, |
| 403 _headersSink = new IOSink(outgoing, encoding: Encoding.ASCII), | 410 _headersSink = new IOSink(outgoing, encoding: Encoding.ASCII), |
| 404 headers = new _HttpHeaders(protocolVersion) { | 411 headers = new _HttpHeaders(protocolVersion) { |
| 405 _dataSink = new IOSink(new _HttpOutboundConsumer(this)); | 412 _dataSink = new IOSink(new _HttpOutboundConsumer(this)); |
| 406 } | 413 } |
| 407 | 414 |
| 408 int get contentLength => headers.contentLength; | 415 int get contentLength => headers.contentLength; |
| 409 void set contentLength(int contentLength) { | 416 void set contentLength(int contentLength) { |
| 410 headers.contentLength = contentLength; | 417 headers.contentLength = contentLength; |
| 411 } | 418 } |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 504 return _headersSink.close(); | 511 return _headersSink.close(); |
| 505 } | 512 } |
| 506 stream = stream.transform(new _BufferTransformer()); | 513 stream = stream.transform(new _BufferTransformer()); |
| 507 if (headers.chunkedTransferEncoding) { | 514 if (headers.chunkedTransferEncoding) { |
| 508 if (_asGZip) { | 515 if (_asGZip) { |
| 509 stream = stream.transform(new ZLibDeflater(gzip: true, level: 6)); | 516 stream = stream.transform(new ZLibDeflater(gzip: true, level: 6)); |
| 510 } | 517 } |
| 511 stream = stream.transform(new _ChunkedTransformer()); | 518 stream = stream.transform(new _ChunkedTransformer()); |
| 512 } else if (contentLength >= 0) { | 519 } else if (contentLength >= 0) { |
| 513 stream = stream.transform( | 520 stream = stream.transform( |
| 514 new _ContentLengthValidator(contentLength)); | 521 new _ContentLengthValidator(contentLength, _uri)); |
| 515 } | 522 } |
| 516 return _headersSink.addStream(stream); | 523 return _headersSink.addStream(stream); |
| 517 }); | 524 }); |
| 518 } | 525 } |
| 519 | 526 |
| 520 Future _close() { | 527 Future _close() { |
| 521 // TODO(ajohnsen): Currently, contentLength, chunkedTransferEncoding and | 528 // TODO(ajohnsen): Currently, contentLength, chunkedTransferEncoding and |
| 522 // persistentConnection is not guaranteed to be in sync. | 529 // persistentConnection is not guaranteed to be in sync. |
| 523 if (!_headersWritten) { | 530 if (!_headersWritten) { |
| 524 if (!_ignoreBody && headers.contentLength == -1) { | 531 if (!_ignoreBody && headers.contentLength == -1) { |
| 525 // If no body was written, _ignoreBody is false (it's not a HEAD | 532 // If no body was written, _ignoreBody is false (it's not a HEAD |
| 526 // request) and the content-length is unspecified, set contentLength to | 533 // request) and the content-length is unspecified, set contentLength to |
| 527 // 0. | 534 // 0. |
| 528 headers.chunkedTransferEncoding = false; | 535 headers.chunkedTransferEncoding = false; |
| 529 headers.contentLength = 0; | 536 headers.contentLength = 0; |
| 530 } else if (!_ignoreBody && headers.contentLength > 0) { | 537 } else if (!_ignoreBody && headers.contentLength > 0) { |
| 531 _headersSink.close().catchError((_) {}); | 538 _headersSink.close().catchError((_) {}); |
| 532 return new Future.error(new HttpException( | 539 return new Future.error(new HttpException( |
| 533 "No content while contentLength was specified to be greater " | 540 "No content while contentLength was specified to be greater " |
| 534 " than 0: ${headers.contentLength}.")); | 541 " than 0: ${headers.contentLength}.", |
| 542 uri: _uri)); | |
| 535 } | 543 } |
| 536 } | 544 } |
| 537 return _writeHeaders().then((_) => _headersSink.close()); | 545 return _writeHeaders().then((_) => _headersSink.close()); |
| 538 } | 546 } |
| 539 | 547 |
| 540 void _writeHeader(); // TODO(ajohnsen): Better name. | 548 void _writeHeader(); // TODO(ajohnsen): Better name. |
| 541 } | 549 } |
| 542 | 550 |
| 543 | 551 |
| 544 class _HttpOutboundConsumer implements StreamConsumer { | 552 class _HttpOutboundConsumer implements StreamConsumer { |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 669 } | 677 } |
| 670 | 678 |
| 671 | 679 |
| 672 class _HttpResponse extends _HttpOutboundMessage<HttpResponse> | 680 class _HttpResponse extends _HttpOutboundMessage<HttpResponse> |
| 673 implements HttpResponse { | 681 implements HttpResponse { |
| 674 int statusCode = 200; | 682 int statusCode = 200; |
| 675 String _reasonPhrase; | 683 String _reasonPhrase; |
| 676 List<Cookie> _cookies; | 684 List<Cookie> _cookies; |
| 677 _HttpRequest _httpRequest; | 685 _HttpRequest _httpRequest; |
| 678 | 686 |
| 679 _HttpResponse(String protocolVersion, | 687 _HttpResponse(Uri uri, |
| 688 String protocolVersion, | |
| 680 _HttpOutgoing _outgoing, | 689 _HttpOutgoing _outgoing, |
| 681 String serverHeader) | 690 String serverHeader) |
| 682 : super(protocolVersion, _outgoing) { | 691 : super(uri, protocolVersion, _outgoing) { |
| 683 if (serverHeader != null) headers.set('Server', serverHeader); | 692 if (serverHeader != null) headers.set('Server', serverHeader); |
| 684 } | 693 } |
| 685 | 694 |
| 686 List<Cookie> get cookies { | 695 List<Cookie> get cookies { |
| 687 if (_cookies == null) _cookies = new List<Cookie>(); | 696 if (_cookies == null) _cookies = new List<Cookie>(); |
| 688 return _cookies; | 697 return _cookies; |
| 689 } | 698 } |
| 690 | 699 |
| 691 String get reasonPhrase => _findReasonPhrase(statusCode); | 700 String get reasonPhrase => _findReasonPhrase(statusCode); |
| 692 void set reasonPhrase(String reasonPhrase) { | 701 void set reasonPhrase(String reasonPhrase) { |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 837 Future<HttpClientResponse> _response; | 846 Future<HttpClientResponse> _response; |
| 838 | 847 |
| 839 // TODO(ajohnsen): Get default value from client? | 848 // TODO(ajohnsen): Get default value from client? |
| 840 bool _followRedirects = true; | 849 bool _followRedirects = true; |
| 841 | 850 |
| 842 int _maxRedirects = 5; | 851 int _maxRedirects = 5; |
| 843 | 852 |
| 844 List<RedirectInfo> _responseRedirects = []; | 853 List<RedirectInfo> _responseRedirects = []; |
| 845 | 854 |
| 846 _HttpClientRequest(_HttpOutgoing outgoing, | 855 _HttpClientRequest(_HttpOutgoing outgoing, |
| 847 Uri this.uri, | 856 Uri uri, |
| 848 String this.method, | 857 String this.method, |
| 849 _Proxy this._proxy, | 858 _Proxy this._proxy, |
| 850 _HttpClient this._httpClient, | 859 _HttpClient this._httpClient, |
| 851 _HttpClientConnection this._httpClientConnection) | 860 _HttpClientConnection this._httpClientConnection) |
| 852 : super("1.1", outgoing) { | 861 : super(uri, "1.1", outgoing), |
| 862 uri = uri { | |
| 853 // GET and HEAD have 'content-length: 0' by default. | 863 // GET and HEAD have 'content-length: 0' by default. |
| 854 if (method == "GET" || method == "HEAD") { | 864 if (method == "GET" || method == "HEAD") { |
| 855 contentLength = 0; | 865 contentLength = 0; |
| 856 } | 866 } |
| 857 } | 867 } |
| 858 | 868 |
| 859 Future<HttpClientResponse> get done { | 869 Future<HttpClientResponse> get done { |
| 860 if (_response == null) { | 870 if (_response == null) { |
| 861 _response = Future.wait([_responseCompleter.future, | 871 _response = Future.wait([_responseCompleter.future, |
| 862 super.done]) | 872 super.done]) |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1042 | 1052 |
| 1043 static List<int> get _chunk0Length => new Uint8List.fromList( | 1053 static List<int> get _chunk0Length => new Uint8List.fromList( |
| 1044 const [0x30, _CharCode.CR, _CharCode.LF, _CharCode.CR, _CharCode.LF]); | 1054 const [0x30, _CharCode.CR, _CharCode.LF, _CharCode.CR, _CharCode.LF]); |
| 1045 } | 1055 } |
| 1046 | 1056 |
| 1047 | 1057 |
| 1048 // Transformer that validates the content length. | 1058 // Transformer that validates the content length. |
| 1049 class _ContentLengthValidator | 1059 class _ContentLengthValidator |
| 1050 extends StreamEventTransformer<List<int>, List<int>> { | 1060 extends StreamEventTransformer<List<int>, List<int>> { |
| 1051 final int expectedContentLength; | 1061 final int expectedContentLength; |
| 1062 final Uri uri; | |
| 1052 int _bytesWritten = 0; | 1063 int _bytesWritten = 0; |
| 1053 | 1064 |
| 1054 _ContentLengthValidator(int this.expectedContentLength); | 1065 _ContentLengthValidator(int this.expectedContentLength, Uri this.uri); |
| 1055 | 1066 |
| 1056 void handleData(List<int> data, EventSink<List<int>> sink) { | 1067 void handleData(List<int> data, EventSink<List<int>> sink) { |
| 1057 _bytesWritten += data.length; | 1068 _bytesWritten += data.length; |
| 1058 if (_bytesWritten > expectedContentLength) { | 1069 if (_bytesWritten > expectedContentLength) { |
| 1059 sink.addError(new HttpException( | 1070 sink.addError(new HttpException( |
| 1060 "Content size exceeds specified contentLength. " | 1071 "Content size exceeds specified contentLength. " |
| 1061 "$_bytesWritten bytes written while expected " | 1072 "$_bytesWritten bytes written while expected " |
| 1062 "$expectedContentLength. " | 1073 "$expectedContentLength. " |
| 1063 "[${new String.fromCharCodes(data)}]")); | 1074 "[${new String.fromCharCodes(data)}]", |
| 1075 uri: uri)); | |
| 1064 sink.close(); | 1076 sink.close(); |
| 1065 } else { | 1077 } else { |
| 1066 sink.add(data); | 1078 sink.add(data); |
| 1067 } | 1079 } |
| 1068 } | 1080 } |
| 1069 | 1081 |
| 1070 void handleDone(EventSink<List<int>> sink) { | 1082 void handleDone(EventSink<List<int>> sink) { |
| 1071 if (_bytesWritten < expectedContentLength) { | 1083 if (_bytesWritten < expectedContentLength) { |
| 1072 sink.addError(new HttpException( | 1084 sink.addError(new HttpException( |
| 1073 "Content size below specified contentLength. " | 1085 "Content size below specified contentLength. " |
| 1074 " $_bytesWritten bytes written while expected " | 1086 " $_bytesWritten bytes written while expected " |
| 1075 "$expectedContentLength.")); | 1087 "$expectedContentLength.", |
| 1088 uri: uri)); | |
| 1076 } | 1089 } |
| 1077 sink.close(); | 1090 sink.close(); |
| 1078 } | 1091 } |
| 1079 } | 1092 } |
| 1080 | 1093 |
| 1081 | 1094 |
| 1082 // Extends StreamConsumer as this is an internal type, only used to pipe to. | 1095 // Extends StreamConsumer as this is an internal type, only used to pipe to. |
| 1083 class _HttpOutgoing implements StreamConsumer<List<int>> { | 1096 class _HttpOutgoing implements StreamConsumer<List<int>> { |
| 1084 final Completer _doneCompleter = new Completer(); | 1097 final Completer _doneCompleter = new Completer(); |
| 1085 final StreamConsumer _consumer; | 1098 final StreamConsumer _consumer; |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 1105 class _HttpClientConnection { | 1118 class _HttpClientConnection { |
| 1106 final String key; | 1119 final String key; |
| 1107 final Socket _socket; | 1120 final Socket _socket; |
| 1108 final bool _proxyTunnel; | 1121 final bool _proxyTunnel; |
| 1109 final _HttpParser _httpParser; | 1122 final _HttpParser _httpParser; |
| 1110 StreamSubscription _subscription; | 1123 StreamSubscription _subscription; |
| 1111 final _HttpClient _httpClient; | 1124 final _HttpClient _httpClient; |
| 1112 bool _dispose = false; | 1125 bool _dispose = false; |
| 1113 Timer _idleTimer; | 1126 Timer _idleTimer; |
| 1114 bool closed = false; | 1127 bool closed = false; |
| 1128 Uri _currentUri; | |
| 1115 | 1129 |
| 1116 Completer<_HttpIncoming> _nextResponseCompleter; | 1130 Completer<_HttpIncoming> _nextResponseCompleter; |
| 1117 Future _streamFuture; | 1131 Future _streamFuture; |
| 1118 | 1132 |
| 1119 _HttpClientConnection(String this.key, | 1133 _HttpClientConnection(String this.key, |
| 1120 Socket this._socket, | 1134 Socket this._socket, |
| 1121 _HttpClient this._httpClient, | 1135 _HttpClient this._httpClient, |
| 1122 [this._proxyTunnel = false]) | 1136 [this._proxyTunnel = false]) |
| 1123 : _httpParser = new _HttpParser.responseParser() { | 1137 : _httpParser = new _HttpParser.responseParser() { |
| 1124 _socket.pipe(_httpParser); | 1138 _socket.pipe(_httpParser); |
| 1125 | 1139 |
| 1126 // Set up handlers on the parser here, so we are sure to get 'onDone' from | 1140 // Set up handlers on the parser here, so we are sure to get 'onDone' from |
| 1127 // the parser. | 1141 // the parser. |
| 1128 _subscription = _httpParser.listen( | 1142 _subscription = _httpParser.listen( |
| 1129 (incoming) { | 1143 (incoming) { |
| 1130 // Only handle one incoming response at the time. Keep the | 1144 // Only handle one incoming response at the time. Keep the |
| 1131 // stream paused until the response have been processed. | 1145 // stream paused until the response have been processed. |
| 1132 _subscription.pause(); | 1146 _subscription.pause(); |
| 1133 // We assume the response is not here, until we have send the request. | 1147 // We assume the response is not here, until we have send the request. |
| 1134 if (_nextResponseCompleter == null) { | 1148 if (_nextResponseCompleter == null) { |
| 1135 throw new HttpException("Unexpected response."); | 1149 throw new HttpException("Unexpected response.", uri: _currentUri); |
| 1136 } | 1150 } |
| 1137 _nextResponseCompleter.complete(incoming); | 1151 _nextResponseCompleter.complete(incoming); |
| 1138 _nextResponseCompleter = null; | 1152 _nextResponseCompleter = null; |
| 1139 }, | 1153 }, |
| 1140 onError: (error) { | 1154 onError: (error) { |
| 1141 if (_nextResponseCompleter != null) { | 1155 if (_nextResponseCompleter != null) { |
| 1142 _nextResponseCompleter.completeError(error); | 1156 _nextResponseCompleter.completeError( |
| 1157 new HttpException(error.message, uri: _currentUri)); | |
| 1143 _nextResponseCompleter = null; | 1158 _nextResponseCompleter = null; |
| 1144 } | 1159 } |
| 1145 }, | 1160 }, |
| 1146 onDone: () { | 1161 onDone: () { |
| 1147 if (_nextResponseCompleter != null) { | 1162 if (_nextResponseCompleter != null) { |
| 1148 _nextResponseCompleter.completeError(new HttpException( | 1163 _nextResponseCompleter.completeError(new HttpException( |
| 1149 "Connection closed before response was received")); | 1164 "Connection closed before response was received", |
| 1165 uri: _currentUri)); | |
| 1150 _nextResponseCompleter = null; | 1166 _nextResponseCompleter = null; |
| 1151 } | 1167 } |
| 1152 close(); | 1168 close(); |
| 1153 }); | 1169 }); |
| 1154 } | 1170 } |
| 1155 | 1171 |
| 1156 _HttpClientRequest send(Uri uri, int port, String method, _Proxy proxy) { | 1172 _HttpClientRequest send(Uri uri, int port, String method, _Proxy proxy) { |
| 1157 if (closed) { | 1173 if (closed) { |
| 1158 throw new HttpException("Socket closed before request was sent"); | 1174 throw new HttpException( |
| 1175 "Socket closed before request was sent", uri: uri); | |
| 1159 } | 1176 } |
| 1177 _currentUri = uri; | |
| 1160 // Start with pausing the parser. | 1178 // Start with pausing the parser. |
| 1161 _subscription.pause(); | 1179 _subscription.pause(); |
| 1162 _ProxyCredentials proxyCreds; // Credentials used to authorize proxy. | 1180 _ProxyCredentials proxyCreds; // Credentials used to authorize proxy. |
| 1163 _SiteCredentials creds; // Credentials used to authorize this request. | 1181 _SiteCredentials creds; // Credentials used to authorize this request. |
| 1164 var outgoing = new _HttpOutgoing(_socket); | 1182 var outgoing = new _HttpOutgoing(_socket); |
| 1165 // Create new request object, wrapping the outgoing connection. | 1183 // Create new request object, wrapping the outgoing connection. |
| 1166 var request = new _HttpClientRequest(outgoing, | 1184 var request = new _HttpClientRequest(outgoing, |
| 1167 uri, | 1185 uri, |
| 1168 method, | 1186 method, |
| 1169 proxy, | 1187 proxy, |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1248 var nextnonce = header.parameters["nextnonce"]; | 1266 var nextnonce = header.parameters["nextnonce"]; |
| 1249 if (nextnonce != null) creds.nonce = nextnonce; | 1267 if (nextnonce != null) creds.nonce = nextnonce; |
| 1250 } | 1268 } |
| 1251 } | 1269 } |
| 1252 request._onIncoming(incoming); | 1270 request._onIncoming(incoming); |
| 1253 }) | 1271 }) |
| 1254 // If we see a state error, we failed to get the 'first' | 1272 // If we see a state error, we failed to get the 'first' |
| 1255 // element. | 1273 // element. |
| 1256 .catchError((error) { | 1274 .catchError((error) { |
| 1257 throw new HttpException( | 1275 throw new HttpException( |
| 1258 "Connection closed before data was received"); | 1276 "Connection closed before data was received", uri); |
| 1259 }, test: (error) => error is StateError) | 1277 }, test: (error) => error is StateError) |
| 1260 .catchError((error) { | 1278 .catchError((error) { |
| 1261 // We are done with the socket. | 1279 // We are done with the socket. |
| 1262 destroy(); | 1280 destroy(); |
| 1263 request._onError(error); | 1281 request._onError(error); |
| 1264 }); | 1282 }); |
| 1265 | 1283 |
| 1266 // Resume the parser now we have a handler. | 1284 // Resume the parser now we have a handler. |
| 1267 _subscription.resume(); | 1285 _subscription.resume(); |
| 1268 return s; | 1286 return s; |
| 1269 }, onError: (e) { | 1287 }, onError: (e) { |
| 1270 destroy(); | 1288 destroy(); |
| 1271 }); | 1289 }); |
|
Bill Hesse
2013/07/05 12:57:45
If _currentUri is used to pass the URI to other me
Anders Johnsen
2013/08/20 05:46:31
Done.
| |
| 1272 return request; | 1290 return request; |
| 1273 } | 1291 } |
| 1274 | 1292 |
| 1275 Future<Socket> detachSocket() { | 1293 Future<Socket> detachSocket() { |
| 1276 return _streamFuture.then( | 1294 return _streamFuture.then( |
| 1277 (_) => new _DetachedSocket(_socket, _httpParser.detachIncoming())); | 1295 (_) => new _DetachedSocket(_socket, _httpParser.detachIncoming())); |
| 1278 } | 1296 } |
| 1279 | 1297 |
| 1280 void destroy() { | 1298 void destroy() { |
| 1281 closed = true; | 1299 closed = true; |
| (...skipping 494 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1776 (incoming) { | 1794 (incoming) { |
| 1777 // If the incoming was closed, close the connection. | 1795 // If the incoming was closed, close the connection. |
| 1778 incoming.dataDone.then((closing) { | 1796 incoming.dataDone.then((closing) { |
| 1779 if (closing) destroy(); | 1797 if (closing) destroy(); |
| 1780 }); | 1798 }); |
| 1781 // Only handle one incoming request at the time. Keep the | 1799 // Only handle one incoming request at the time. Keep the |
| 1782 // stream paused until the request has been send. | 1800 // stream paused until the request has been send. |
| 1783 _subscription.pause(); | 1801 _subscription.pause(); |
| 1784 _state = _ACTIVE; | 1802 _state = _ACTIVE; |
| 1785 var outgoing = new _HttpOutgoing(_socket); | 1803 var outgoing = new _HttpOutgoing(_socket); |
| 1786 var response = new _HttpResponse(incoming.headers.protocolVersion, | 1804 var response = new _HttpResponse(incoming.uri, |
| 1805 incoming.headers.protocolVersion, | |
| 1787 outgoing, | 1806 outgoing, |
| 1788 _httpServer.serverHeader); | 1807 _httpServer.serverHeader); |
| 1789 var request = new _HttpRequest(response, incoming, _httpServer, this); | 1808 var request = new _HttpRequest(response, incoming, _httpServer, this); |
| 1790 _streamFuture = outgoing.done | 1809 _streamFuture = outgoing.done |
| 1791 .then((_) { | 1810 .then((_) { |
| 1792 if (_state == _DETACHED) return; | 1811 if (_state == _DETACHED) return; |
| 1793 if (response.persistentConnection && | 1812 if (response.persistentConnection && |
| 1794 request.persistentConnection && | 1813 request.persistentConnection && |
| 1795 incoming.fullBodyRead) { | 1814 incoming.fullBodyRead) { |
| 1796 _state = _IDLE; | 1815 _state = _IDLE; |
| (...skipping 584 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2381 final Uri location; | 2400 final Uri location; |
| 2382 } | 2401 } |
| 2383 | 2402 |
| 2384 String _getHttpVersion() { | 2403 String _getHttpVersion() { |
| 2385 var version = Platform.version; | 2404 var version = Platform.version; |
| 2386 // Only include major and minor version numbers. | 2405 // Only include major and minor version numbers. |
| 2387 int index = version.indexOf('.', version.indexOf('.') + 1); | 2406 int index = version.indexOf('.', version.indexOf('.') + 1); |
| 2388 version = version.substring(0, index); | 2407 version = version.substring(0, index); |
| 2389 return 'Dart/$version (dart:io)'; | 2408 return 'Dart/$version (dart:io)'; |
| 2390 } | 2409 } |
| OLD | NEW |