Chromium Code Reviews| Index: sdk/lib/io/http_parser.dart |
| diff --git a/sdk/lib/io/http_parser.dart b/sdk/lib/io/http_parser.dart |
| index 4e3ede1d0be829e57ba573a1901bb873ef32cb85..1476346360fa750ebb6fa4dae26f90c863aa9a6f 100644 |
| --- a/sdk/lib/io/http_parser.dart |
| +++ b/sdk/lib/io/http_parser.dart |
| @@ -247,10 +247,10 @@ class _HttpParser extends Stream<_HttpIncoming> { |
| int _httpVersionIndex; |
| int _messageType; |
| int _statusCode = 0; |
| - List _method_or_status_code; |
| - List _uri_or_reason_phrase; |
| - List _headerField; |
| - List _headerValue; |
| + final List<int> _method = []; |
| + final List<int> _uri_or_reason_phrase = []; |
| + final List<int> _headerField = []; |
| + final List<int> _headerValue = []; |
| int _httpVersion; |
| int _transferLength = -1; |
| @@ -258,8 +258,7 @@ class _HttpParser extends Stream<_HttpIncoming> { |
| bool _connectionUpgrade; |
| bool _chunked; |
| - bool _noMessageBody; |
| - String _responseToMethod; // Indicates the method used for the request. |
| + bool _noMessageBody = false; |
| int _remainingContent = -1; |
| _HttpHeaders _headers; |
| @@ -374,7 +373,7 @@ class _HttpParser extends Stream<_HttpIncoming> { |
| if (!_isTokenChar(byte)) { |
| throw new HttpException("Invalid request method"); |
| } |
| - _method_or_status_code.add(byte); |
| + _method.add(byte); |
| if (!_requestParser) { |
| throw new HttpException("Invalid response line"); |
| } |
| @@ -399,12 +398,12 @@ class _HttpParser extends Stream<_HttpIncoming> { |
| } else { |
| // Did not parse HTTP version. Expect method instead. |
| for (int i = 0; i < _httpVersionIndex; i++) { |
| - _method_or_status_code.add(_Const.HTTP[i]); |
| + _method.add(_Const.HTTP[i]); |
| } |
| if (byte == _CharCode.SP) { |
| _state = _State.REQUEST_LINE_URI; |
| } else { |
| - _method_or_status_code.add(byte); |
| + _method.add(byte); |
| _httpVersion = _HttpVersion.UNDETERMINED; |
| if (!_requestParser) { |
| throw new HttpException("Invalid response line"); |
| @@ -449,7 +448,7 @@ class _HttpParser extends Stream<_HttpIncoming> { |
| byte == _CharCode.LF) { |
| throw new HttpException("Invalid request method"); |
| } |
| - _method_or_status_code.add(byte); |
| + _method.add(byte); |
| } |
| break; |
| @@ -500,9 +499,6 @@ class _HttpParser extends Stream<_HttpIncoming> { |
| case _State.RESPONSE_LINE_STATUS_CODE: |
| if (byte == _CharCode.SP) { |
| - if (_method_or_status_code.length != 3) { |
| - throw new HttpException("Invalid response status code"); |
| - } |
| _state = _State.RESPONSE_LINE_REASON_PHRASE; |
| } else if (byte == _CharCode.CR) { |
| // Some HTTP servers does not follow the spec. and send |
| @@ -512,7 +508,7 @@ class _HttpParser extends Stream<_HttpIncoming> { |
| if (byte < 0x30 && 0x39 < byte) { |
| throw new HttpException("Invalid response status code"); |
| } else { |
| - _method_or_status_code.add(byte); |
| + _statusCode = _statusCode * 10 + byte - 0x30; |
|
Søren Gjesse
2014/02/20 14:12:18
As discussed offline, we should keep track of the
Anders Johnsen
2014/02/20 14:46:53
Done.
|
| } |
| } |
| break; |
| @@ -531,14 +527,14 @@ class _HttpParser extends Stream<_HttpIncoming> { |
| case _State.RESPONSE_LINE_ENDING: |
| _expect(byte, _CharCode.LF); |
| _messageType == _MessageType.RESPONSE; |
| - _statusCode = int.parse( |
| - new String.fromCharCodes(_method_or_status_code)); |
| if (_statusCode < 100 || _statusCode > 599) { |
| throw new HttpException("Invalid response status code"); |
| } else { |
| // Check whether this response will never have a body. |
| - _noMessageBody = _statusCode <= 199 || _statusCode == 204 || |
| - _statusCode == 304; |
| + if (_statusCode <= 199 || _statusCode == 204 || |
| + _statusCode == 304) { |
| + _noMessageBody = true; |
| + } |
| } |
| _state = _State.HEADER_START; |
| break; |
| @@ -595,13 +591,14 @@ class _HttpParser extends Stream<_HttpIncoming> { |
| String headerField = new String.fromCharCodes(_headerField); |
| String headerValue = new String.fromCharCodes(_headerValue); |
| if (headerField == "transfer-encoding" && |
| - headerValue.toLowerCase() == "chunked") { |
| + _caseInsensitiveCompare("chunked".codeUnits, _headerValue)) { |
| _chunked = true; |
| } |
| if (headerField == "connection") { |
| List<String> tokens = _tokenizeFieldValue(headerValue); |
| for (int i = 0; i < tokens.length; i++) { |
| - if (tokens[i].toLowerCase() == "upgrade") { |
| + if (_caseInsensitiveCompare("upgrade".codeUnits, |
| + tokens[i].codeUnits)) { |
| _connectionUpgrade = true; |
| } |
| _headers._add(headerField, tokens[i]); |
| @@ -646,7 +643,7 @@ class _HttpParser extends Stream<_HttpIncoming> { |
| _createIncoming(_transferLength); |
| if (_requestParser) { |
| _incoming.method = |
| - new String.fromCharCodes(_method_or_status_code); |
| + new String.fromCharCodes(_method); |
| _incoming.uri = |
| Uri.parse( |
| new String.fromCharCodes(_uri_or_reason_phrase)); |
| @@ -655,7 +652,7 @@ class _HttpParser extends Stream<_HttpIncoming> { |
| _incoming.reasonPhrase = |
| new String.fromCharCodes(_uri_or_reason_phrase); |
| } |
| - _method_or_status_code.clear(); |
| + _method.clear(); |
| _uri_or_reason_phrase.clear(); |
| if (_connectionUpgrade) { |
| _incoming.upgraded = true; |
| @@ -666,8 +663,7 @@ class _HttpParser extends Stream<_HttpIncoming> { |
| return; |
| } |
| if (_transferLength == 0 || |
| - (_messageType == _MessageType.RESPONSE && |
| - (_noMessageBody || _responseToMethod == "HEAD"))) { |
| + (_messageType == _MessageType.RESPONSE && _noMessageBody)) { |
| _reset(); |
| var tmp = _incoming; |
| _closeIncoming(); |
| @@ -866,7 +862,9 @@ class _HttpParser extends Stream<_HttpIncoming> { |
| bool get upgrade => _connectionUpgrade && _state == _State.UPGRADED; |
| bool get persistentConnection => _persistentConnection; |
| - void set responseToMethod(String method) { _responseToMethod = method; } |
| + void set isHead(bool value) { |
| + if (value) _noMessageBody = true; |
| + } |
| _HttpDetachedIncoming detachIncoming() { |
| // Simulate detached by marking as upgraded. |
| @@ -887,10 +885,10 @@ class _HttpParser extends Stream<_HttpIncoming> { |
| if (_state == _State.UPGRADED) return; |
| _state = _State.START; |
| _messageType = _MessageType.UNDETERMINED; |
| - _headerField = new List(); |
| - _headerValue = new List(); |
| - _method_or_status_code = new List(); |
| - _uri_or_reason_phrase = new List(); |
| + _headerField.clear(); |
| + _headerValue.clear(); |
| + _method.clear(); |
| + _uri_or_reason_phrase.clear(); |
| _statusCode = 0; |
| @@ -901,7 +899,6 @@ class _HttpParser extends Stream<_HttpIncoming> { |
| _chunked = false; |
| _noMessageBody = false; |
| - _responseToMethod = null; |
| _remainingContent = -1; |
| _headers = null; |
| @@ -940,6 +937,15 @@ class _HttpParser extends Stream<_HttpIncoming> { |
| return (aCode <= byte && byte <= zCode) ? byte + delta : byte; |
| } |
| + // expected should already be lowercase. |
| + bool _caseInsensitiveCompare(List<int> expected, List<int> value) { |
| + if (expected.length != value.length) return false; |
| + for (int i = 0; i < expected.length; i++) { |
| + if (expected[i] != _toLowerCase(value[i])) return false; |
| + } |
| + return true; |
| + } |
| + |
| int _expect(int val1, int val2) { |
| if (val1 != val2) { |
| throw new HttpException("Failed to parse HTTP"); |