Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(674)

Unified Diff: sdk/lib/io/http_parser.dart

Issue 1078683002: Be more lean when parsing HTTP headers (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Addressed review comments Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | tests/standalone/io/http_parser_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sdk/lib/io/http_parser.dart
diff --git a/sdk/lib/io/http_parser.dart b/sdk/lib/io/http_parser.dart
index 09f06eaee38b5cff19d0d0095850d4c2a9ac0ddc..e7415cf49e33e90a216bbad1d559f65363a8afe2 100644
--- a/sdk/lib/io/http_parser.dart
+++ b/sdk/lib/io/http_parser.dart
@@ -334,6 +334,74 @@ class _HttpParser extends Stream<_HttpIncoming> {
}
}
+ // Process end of headers. Returns true if the parser should stop
+ // parsing and return. This will be in case of either an upgrade
+ // request or a request or response with an empty body.
+ bool _headersEnd() {
+ _headers._mutable = false;
+
+ _transferLength = _headers.contentLength;
+ // Ignore the Content-Length header if Transfer-Encoding
+ // is chunked (RFC 2616 section 4.4)
+ if (_chunked) _transferLength = -1;
+
+ // If a request message has neither Content-Length nor
+ // Transfer-Encoding the message must not have a body (RFC
+ // 2616 section 4.3).
+ if (_messageType == _MessageType.REQUEST &&
+ _transferLength < 0 &&
+ _chunked == false) {
+ _transferLength = 0;
+ }
+ if (_connectionUpgrade) {
+ _state = _State.UPGRADED;
+ _transferLength = 0;
+ }
+ _createIncoming(_transferLength);
+ if (_requestParser) {
+ _incoming.method =
+ new String.fromCharCodes(_method);
+ _incoming.uri =
+ Uri.parse(
+ new String.fromCharCodes(_uri_or_reason_phrase));
+ } else {
+ _incoming.statusCode = _statusCode;
+ _incoming.reasonPhrase =
+ new String.fromCharCodes(_uri_or_reason_phrase);
+ }
+ _method.clear();
+ _uri_or_reason_phrase.clear();
+ if (_connectionUpgrade) {
+ _incoming.upgraded = true;
+ _parserCalled = false;
+ var tmp = _incoming;
+ _closeIncoming();
+ _controller.add(tmp);
+ return true;
+ }
+ if (_transferLength == 0 ||
+ (_messageType == _MessageType.RESPONSE && _noMessageBody)) {
+ _reset();
+ var tmp = _incoming;
+ _closeIncoming();
+ _controller.add(tmp);
+ return false;
+ } else if (_chunked) {
+ _state = _State.CHUNK_SIZE;
+ _remainingContent = 0;
+ } else if (_transferLength > 0) {
+ _remainingContent = _transferLength;
+ _state = _State.BODY;
+ } else {
+ // Neither chunked nor content length. End of body
+ // indicated by close.
+ _state = _State.BODY;
+ }
+ _parserCalled = false;
+ _controller.add(_incoming);
+ return true;
+ }
+
// From RFC 2616.
// generic-message = start-line
// *(message-header CRLF)
@@ -487,8 +555,13 @@ class _HttpParser extends Stream<_HttpIncoming> {
throw new HttpException("Invalid response line");
}
} else {
- _expect(byte, _CharCode.CR);
- _state = _State.REQUEST_LINE_ENDING;
+ if (byte == _CharCode.CR) {
+ _state = _State.REQUEST_LINE_ENDING;
+ } else {
+ _expect(byte, _CharCode.LF);
+ _messageType = _MessageType.REQUEST;
+ _state = _State.HEADER_START;
+ }
}
break;
@@ -545,6 +618,12 @@ class _HttpParser extends Stream<_HttpIncoming> {
_headers = new _HttpHeaders(version);
if (byte == _CharCode.CR) {
_state = _State.HEADER_ENDING;
+ } else if (byte == _CharCode.LF) {
+ if (_headersEnd()) {
+ return;
+ } else {
+ break;
+ }
} else {
// Start of new header field.
_headerField.add(_toLowerCaseByte(byte));
@@ -566,6 +645,8 @@ class _HttpParser extends Stream<_HttpIncoming> {
case _State.HEADER_VALUE_START:
if (byte == _CharCode.CR) {
_state = _State.HEADER_VALUE_FOLDING_OR_ENDING;
+ } else if (byte == _CharCode.LF) {
+ _state = _State.HEADER_VALUE_FOLD_OR_END;
} else if (byte != _CharCode.SP && byte != _CharCode.HT) {
// Start of new header value.
_headerValue.add(byte);
@@ -576,6 +657,8 @@ class _HttpParser extends Stream<_HttpIncoming> {
case _State.HEADER_VALUE:
if (byte == _CharCode.CR) {
_state = _State.HEADER_VALUE_FOLDING_OR_ENDING;
+ } else if (byte == _CharCode.LF) {
+ _state = _State.HEADER_VALUE_FOLD_OR_END;
} else {
_headerValue.add(byte);
}
@@ -613,6 +696,12 @@ class _HttpParser extends Stream<_HttpIncoming> {
if (byte == _CharCode.CR) {
_state = _State.HEADER_ENDING;
+ } else if (byte == _CharCode.LF) {
+ if (_headersEnd()) {
+ return;
+ } else {
+ break;
+ }
} else {
// Start of new header field.
_headerField.add(_toLowerCaseByte(byte));
@@ -623,67 +712,11 @@ class _HttpParser extends Stream<_HttpIncoming> {
case _State.HEADER_ENDING:
_expect(byte, _CharCode.LF);
- _headers._mutable = false;
-
- _transferLength = _headers.contentLength;
- // Ignore the Content-Length header if Transfer-Encoding
- // is chunked (RFC 2616 section 4.4)
- if (_chunked) _transferLength = -1;
-
- // If a request message has neither Content-Length nor
- // Transfer-Encoding the message must not have a body (RFC
- // 2616 section 4.3).
- if (_messageType == _MessageType.REQUEST &&
- _transferLength < 0 &&
- _chunked == false) {
- _transferLength = 0;
- }
- if (_connectionUpgrade) {
- _state = _State.UPGRADED;
- _transferLength = 0;
- }
- _createIncoming(_transferLength);
- if (_requestParser) {
- _incoming.method =
- new String.fromCharCodes(_method);
- _incoming.uri =
- Uri.parse(
- new String.fromCharCodes(_uri_or_reason_phrase));
- } else {
- _incoming.statusCode = _statusCode;
- _incoming.reasonPhrase =
- new String.fromCharCodes(_uri_or_reason_phrase);
- }
- _method.clear();
- _uri_or_reason_phrase.clear();
- if (_connectionUpgrade) {
- _incoming.upgraded = true;
- _parserCalled = false;
- var tmp = _incoming;
- _closeIncoming();
- _controller.add(tmp);
+ if (_headersEnd()) {
return;
- }
- if (_transferLength == 0 ||
- (_messageType == _MessageType.RESPONSE && _noMessageBody)) {
- _reset();
- var tmp = _incoming;
- _closeIncoming();
- _controller.add(tmp);
- break;
- } else if (_chunked) {
- _state = _State.CHUNK_SIZE;
- _remainingContent = 0;
- } else if (_transferLength > 0) {
- _remainingContent = _transferLength;
- _state = _State.BODY;
} else {
- // Neither chunked nor content length. End of body
- // indicated by close.
- _state = _State.BODY;
+ break;
}
- _parserCalled = false;
- _controller.add(_incoming);
return;
case _State.CHUNK_SIZE_STARTING_CR:
« no previous file with comments | « no previous file | tests/standalone/io/http_parser_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698