Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 // The close queue handles graceful closing of HTTP connections. When | 5 // The close queue handles graceful closing of HTTP connections. When |
| 6 // a connection is added to the queue it will enter a wait state | 6 // a connection is added to the queue it will enter a wait state |
| 7 // waiting for all data written and possibly socket shutdown from | 7 // waiting for all data written and possibly socket shutdown from |
| 8 // peer. | 8 // peer. |
| 9 class _CloseQueue { | 9 class _CloseQueue { |
| 10 _CloseQueue() : _q = new Set<_HttpConnectionBase>(); | 10 _CloseQueue() : _q = new Set<_HttpConnectionBase>(); |
| (...skipping 814 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 825 while (!_buffer.isEmpty) { | 825 while (!_buffer.isEmpty) { |
| 826 var data = _buffer.first; | 826 var data = _buffer.first; |
| 827 _socket.outputStream.write(data, false); | 827 _socket.outputStream.write(data, false); |
| 828 _buffer.removeBytes(data.length); | 828 _buffer.removeBytes(data.length); |
| 829 } | 829 } |
| 830 _buffer = null; | 830 _buffer = null; |
| 831 } | 831 } |
| 832 } | 832 } |
| 833 | 833 |
| 834 bool _write(List<int> data, [bool copyBuffer = false]) { | 834 bool _write(List<int> data, [bool copyBuffer = false]) { |
| 835 if (_isRequestDone) { | 835 if (_isRequestDone || !_hasBody || _httpParser.upgrade) { |
| 836 return _socket.outputStream.write(data, copyBuffer); | 836 return _socket.outputStream.write(data, copyBuffer); |
| 837 } else { | 837 } else { |
| 838 _bufferData(data, copyBuffer); | 838 _bufferData(data, copyBuffer); |
| 839 return false; | 839 return false; |
| 840 } | 840 } |
| 841 } | 841 } |
| 842 | 842 |
| 843 bool _writeFrom(List<int> data, [int offset, int len]) { | 843 bool _writeFrom(List<int> data, [int offset, int len]) { |
| 844 if (_isRequestDone) { | 844 if (_isRequestDone || !_hasBody || _httpParser.upgrade) { |
| 845 return _socket.outputStream.writeFrom(data, offset, len); | 845 return _socket.outputStream.writeFrom(data, offset, len); |
| 846 } else { | 846 } else { |
| 847 if (offset == null) offset = 0; | 847 if (offset == null) offset = 0; |
| 848 if (len == null) len = buffer.length - offset; | 848 if (len == null) len = buffer.length - offset; |
| 849 _bufferData(data.getRange(offset, len), false); | 849 _bufferData(data.getRange(offset, len), false); |
| 850 return false; | 850 return false; |
| 851 } | 851 } |
| 852 } | 852 } |
| 853 | 853 |
| 854 bool _flush() { | 854 bool _flush() { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 888 } | 888 } |
| 889 if (_response != null && _response._streamErrorHandler != null) { | 889 if (_response != null && _response._streamErrorHandler != null) { |
| 890 _response._streamErrorHandler(e); | 890 _response._streamErrorHandler(e); |
| 891 } | 891 } |
| 892 if (_socket != null) _socket.close(); | 892 if (_socket != null) _socket.close(); |
| 893 } | 893 } |
| 894 | 894 |
| 895 void _onRequestReceived(String method, | 895 void _onRequestReceived(String method, |
| 896 String uri, | 896 String uri, |
| 897 String version, | 897 String version, |
| 898 _HttpHeaders headers) { | 898 _HttpHeaders headers, |
| 899 bool hasBody) { | |
| 899 _state = _HttpConnectionBase.ACTIVE; | 900 _state = _HttpConnectionBase.ACTIVE; |
| 900 // Create new request and response objects for this request. | 901 // Create new request and response objects for this request. |
| 901 _request = new _HttpRequest(this); | 902 _request = new _HttpRequest(this); |
| 902 _response = new _HttpResponse(this); | 903 _response = new _HttpResponse(this); |
| 903 _request._onRequestReceived(method, uri, version, headers); | 904 _request._onRequestReceived(method, uri, version, headers); |
| 904 _request._protocolVersion = version; | 905 _request._protocolVersion = version; |
| 905 _response._protocolVersion = version; | 906 _response._protocolVersion = version; |
| 906 _response._headResponse = method == "HEAD"; | 907 _response._headResponse = method == "HEAD"; |
| 907 _response.persistentConnection = _httpParser.persistentConnection; | 908 _response.persistentConnection = _httpParser.persistentConnection; |
| 909 _hasBody = hasBody; | |
| 908 if (onRequestReceived != null) { | 910 if (onRequestReceived != null) { |
| 909 onRequestReceived(_request, _response); | 911 onRequestReceived(_request, _response); |
| 910 } | 912 } |
| 913 _checkDone(); | |
| 911 } | 914 } |
| 912 | 915 |
| 913 void _onDataReceived(List<int> data) { | 916 void _onDataReceived(List<int> data) { |
| 914 _request._onDataReceived(data); | 917 _request._onDataReceived(data); |
| 918 _checkDone(); | |
| 915 } | 919 } |
| 916 | 920 |
| 917 void _checkDone() { | 921 void _checkDone() { |
| 918 if (_isReadClosed) { | 922 if (_isReadClosed) { |
| 919 // If the client closes the conversation is ended. | 923 // If the client closes the conversation is ended. |
| 920 _server._closeQueue.add(this); | 924 _server._closeQueue.add(this); |
| 921 } else if (_isAllDone) { | 925 } else if (_isAllDone) { |
| 922 // If we are done writing the response, and the connection is | 926 // If we are done writing the response, and the connection is |
| 923 // not persistent, we must close. Also if using HTTP 1.0 and the | 927 // not persistent, we must close. Also if using HTTP 1.0 and the |
| 924 // content length was not known we must close to indicate end of | 928 // content length was not known we must close to indicate end of |
| 925 // body. | 929 // body. |
| 926 bool close = | 930 bool close = |
| 927 !_response.persistentConnection || | 931 !_response.persistentConnection || |
| 928 (_response._protocolVersion == "1.0" && _response._contentLength < 0); | 932 (_response._protocolVersion == "1.0" && _response._contentLength < 0); |
| 929 _request = null; | 933 _request = null; |
| 930 _response = null; | 934 _response = null; |
| 931 if (close) { | 935 if (close) { |
| 932 _server._closeQueue.add(this); | 936 _server._closeQueue.add(this); |
| 933 } else { | 937 } else { |
| 934 _state = _HttpConnectionBase.IDLE; | 938 _state = _HttpConnectionBase.IDLE; |
| 935 } | 939 } |
| 936 } else if (_isResponseDone) { | 940 } else if (_isResponseDone && _hasBody) { |
| 937 // If the response is closed before the request is fully read | 941 // If the response is closed before the request is fully read |
| 938 // close this connection. If there is buffered output | 942 // close this connection. If there is buffered output |
| 939 // (e.g. error response for invalid request where the server did | 943 // (e.g. error response for invalid request where the server did |
| 940 // not care to read the request body) this is send. | 944 // not care to read the request body) this is send. |
| 941 assert(!_isRequestDone); | 945 assert(!_isRequestDone); |
| 942 _writeBufferedResponse(); | 946 _writeBufferedResponse(); |
| 943 _close(); | 947 _close(); |
| 944 _server._closeQueue.add(this); | 948 _server._closeQueue.add(this); |
| 945 } | 949 } |
| 946 } | 950 } |
| 947 | 951 |
| 948 void _onDataEnd(bool close) { | 952 void _onDataEnd(bool close) { |
| 949 // Start sending queued response if any. | 953 // Start sending queued response if any. |
| 954 _state |= _HttpConnectionBase.REQUEST_DONE; | |
| 950 _writeBufferedResponse(); | 955 _writeBufferedResponse(); |
| 951 _state |= _HttpConnectionBase.REQUEST_DONE; | |
| 952 _request._onDataEnd(); | 956 _request._onDataEnd(); |
| 957 _checkDone(); | |
| 953 } | 958 } |
| 954 | 959 |
| 955 void _responseClosed() { | 960 void _responseClosed() { |
| 956 _state |= _HttpConnectionBase.RESPONSE_DONE; | 961 _state |= _HttpConnectionBase.RESPONSE_DONE; |
| 957 _checkDone(); | |
| 958 } | 962 } |
| 959 | 963 |
| 960 HttpServer _server; | 964 HttpServer _server; |
| 961 HttpRequest _request; | 965 HttpRequest _request; |
| 962 HttpResponse _response; | 966 HttpResponse _response; |
| 967 bool _hasBody = false; | |
| 963 | 968 |
| 964 // Buffer for data written before full response has been processed. | 969 // Buffer for data written before full response has been processed. |
| 965 _BufferList _buffer; | 970 _BufferList _buffer; |
| 966 | 971 |
| 967 // Callbacks. | 972 // Callbacks. |
| 968 Function onRequestReceived; | 973 Function onRequestReceived; |
| 969 Function onError; | 974 Function onError; |
| 970 } | 975 } |
| 971 | 976 |
| 972 | 977 |
| (...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1307 InputStream get inputStream { | 1312 InputStream get inputStream { |
| 1308 if (_inputStream == null) { | 1313 if (_inputStream == null) { |
| 1309 _inputStream = new _HttpInputStream(this); | 1314 _inputStream = new _HttpInputStream(this); |
| 1310 } | 1315 } |
| 1311 return _inputStream; | 1316 return _inputStream; |
| 1312 } | 1317 } |
| 1313 | 1318 |
| 1314 void _onResponseReceived(int statusCode, | 1319 void _onResponseReceived(int statusCode, |
| 1315 String reasonPhrase, | 1320 String reasonPhrase, |
| 1316 String version, | 1321 String version, |
| 1317 _HttpHeaders headers) { | 1322 _HttpHeaders headers, |
| 1323 bool hasBody) { | |
| 1318 _statusCode = statusCode; | 1324 _statusCode = statusCode; |
| 1319 _reasonPhrase = reasonPhrase; | 1325 _reasonPhrase = reasonPhrase; |
| 1320 _headers = headers; | 1326 _headers = headers; |
| 1321 // Get parsed content length. | 1327 // Get parsed content length. |
| 1322 _contentLength = _httpConnection._httpParser.contentLength; | 1328 _contentLength = _httpConnection._httpParser.contentLength; |
| 1323 | 1329 |
| 1324 // Prepare for receiving data. | 1330 // Prepare for receiving data. |
| 1325 _headers._mutable = false; | 1331 _headers._mutable = false; |
| 1326 _buffer = new _BufferList(); | 1332 _buffer = new _BufferList(); |
| 1327 | |
| 1328 if (isRedirect && _connection.followRedirects) { | 1333 if (isRedirect && _connection.followRedirects) { |
| 1329 if (_connection._redirects == null || | 1334 if (_connection._redirects == null || |
| 1330 _connection._redirects.length < _connection.maxRedirects) { | 1335 _connection._redirects.length < _connection.maxRedirects) { |
| 1331 // Check the location header. | 1336 // Check the location header. |
| 1332 List<String> location = headers[HttpHeaders.LOCATION]; | 1337 List<String> location = headers[HttpHeaders.LOCATION]; |
| 1333 if (location == null || location.length > 1) { | 1338 if (location == null || location.length > 1) { |
| 1334 throw new RedirectException("Invalid redirect", | 1339 throw new RedirectException("Invalid redirect", |
| 1335 _connection._redirects); | 1340 _connection._redirects); |
| 1336 } | 1341 } |
| 1337 // Check for redirect loop | 1342 // Check for redirect loop |
| (...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1608 _onErrorCallback(e); | 1613 _onErrorCallback(e); |
| 1609 } else { | 1614 } else { |
| 1610 throw e; | 1615 throw e; |
| 1611 } | 1616 } |
| 1612 } | 1617 } |
| 1613 } | 1618 } |
| 1614 | 1619 |
| 1615 void _onResponseReceived(int statusCode, | 1620 void _onResponseReceived(int statusCode, |
| 1616 String reasonPhrase, | 1621 String reasonPhrase, |
| 1617 String version, | 1622 String version, |
| 1618 _HttpHeaders headers) { | 1623 _HttpHeaders headers, |
| 1619 _response._onResponseReceived(statusCode, reasonPhrase, version, headers); | 1624 bool hasBody) { |
|
Mads Ager (google)
2012/12/11 07:04:34
indentation off by 1 space?
Søren Gjesse
2012/12/11 07:26:31
Done.
| |
| 1625 _response._onResponseReceived( | |
| 1626 statusCode, reasonPhrase, version, headers, hasBody); | |
| 1620 } | 1627 } |
| 1621 | 1628 |
| 1622 void _onDataReceived(List<int> data) { | 1629 void _onDataReceived(List<int> data) { |
| 1623 _response._onDataReceived(data); | 1630 _response._onDataReceived(data); |
| 1624 } | 1631 } |
| 1625 | 1632 |
| 1626 void _onDataEnd(bool close) { | 1633 void _onDataEnd(bool close) { |
| 1627 _state |= _HttpConnectionBase.RESPONSE_DONE; | 1634 _state |= _HttpConnectionBase.RESPONSE_DONE; |
| 1628 _response._onDataEnd(); | 1635 _response._onDataEnd(); |
| 1629 _checkSocketDone(); | 1636 _checkSocketDone(); |
| (...skipping 648 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2278 | 2285 |
| 2279 | 2286 |
| 2280 class _RedirectInfo implements RedirectInfo { | 2287 class _RedirectInfo implements RedirectInfo { |
| 2281 const _RedirectInfo(int this.statusCode, | 2288 const _RedirectInfo(int this.statusCode, |
| 2282 String this.method, | 2289 String this.method, |
| 2283 Uri this.location); | 2290 Uri this.location); |
| 2284 final int statusCode; | 2291 final int statusCode; |
| 2285 final String method; | 2292 final String method; |
| 2286 final Uri location; | 2293 final Uri location; |
| 2287 } | 2294 } |
| OLD | NEW |