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

Unified Diff: runtime/bin/http_parser.dart

Issue 11337019: Use patching for dart:io. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address comments Created 8 years, 2 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
Index: runtime/bin/http_parser.dart
diff --git a/runtime/bin/http_parser.dart b/runtime/bin/http_parser.dart
deleted file mode 100644
index a5549c5d3a519fceace71023d934c2330baab503..0000000000000000000000000000000000000000
--- a/runtime/bin/http_parser.dart
+++ /dev/null
@@ -1,733 +0,0 @@
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// Global constants.
-class _Const {
- // Bytes for "HTTP".
- static const HTTP = const [72, 84, 84, 80];
- // Bytes for "HTTP/1.".
- static const HTTP1DOT = const [72, 84, 84, 80, 47, 49, 46];
- // Bytes for "HTTP/1.0".
- static const HTTP10 = const [72, 84, 84, 80, 47, 49, 46, 48];
- // Bytes for "HTTP/1.1".
- static const HTTP11 = const [72, 84, 84, 80, 47, 49, 46, 49];
-
- static const END_CHUNKED = const [0x30, 13, 10, 13, 10];
-
- // Bytes for '()<>@,;:\\"/[]?={} \t'.
- static const SEPARATORS = const [40, 41, 60, 62, 64, 44, 59, 58, 92, 34, 47,
- 91, 93, 63, 61, 123, 125, 32, 9];
-
- // Bytes for '()<>@,;:\\"/[]?={} \t\r\n'.
- static const SEPARATORS_AND_CR_LF = const [40, 41, 60, 62, 64, 44, 59, 58, 92,
- 34, 47, 91, 93, 63, 61, 123, 125,
- 32, 9, 13, 10];
-}
-
-
-// Frequently used character codes.
-class _CharCode {
- static const int HT = 9;
- static const int LF = 10;
- static const int CR = 13;
- static const int SP = 32;
- static const int COMMA = 44;
- static const int DASH = 45;
- static const int SLASH = 47;
- static const int ZERO = 48;
- static const int ONE = 49;
- static const int COLON = 58;
- static const int SEMI_COLON = 59;
-}
-
-
-// States of the HTTP parser state machine.
-class _State {
- static const int START = 0;
- static const int METHOD_OR_RESPONSE_HTTP_VERSION = 1;
- static const int RESPONSE_HTTP_VERSION = 2;
- static const int REQUEST_LINE_METHOD = 3;
- static const int REQUEST_LINE_URI = 4;
- static const int REQUEST_LINE_HTTP_VERSION = 5;
- static const int REQUEST_LINE_ENDING = 6;
- static const int RESPONSE_LINE_STATUS_CODE = 7;
- static const int RESPONSE_LINE_REASON_PHRASE = 8;
- static const int RESPONSE_LINE_ENDING = 9;
- static const int HEADER_START = 10;
- static const int HEADER_FIELD = 11;
- static const int HEADER_VALUE_START = 12;
- static const int HEADER_VALUE = 13;
- static const int HEADER_VALUE_FOLDING_OR_ENDING = 14;
- static const int HEADER_VALUE_FOLD_OR_END = 15;
- static const int HEADER_ENDING = 16;
-
- static const int CHUNK_SIZE_STARTING_CR = 17;
- static const int CHUNK_SIZE_STARTING_LF = 18;
- static const int CHUNK_SIZE = 19;
- static const int CHUNK_SIZE_EXTENSION = 20;
- static const int CHUNK_SIZE_ENDING = 21;
- static const int CHUNKED_BODY_DONE_CR = 22;
- static const int CHUNKED_BODY_DONE_LF = 23;
- static const int BODY = 24;
- static const int CLOSED = 25;
- static const int UPGRADED = 26;
- static const int FAILURE = 27;
-
- static const int FIRST_BODY_STATE = CHUNK_SIZE_STARTING_CR;
-}
-
-// HTTP version of the request or response being parsed.
-class _HttpVersion {
- static const int UNDETERMINED = 0;
- static const int HTTP10 = 1;
- static const int HTTP11 = 2;
-}
-
-// States of the HTTP parser state machine.
-class _MessageType {
- static const int UNDETERMINED = 0;
- static const int REQUEST = 1;
- static const int RESPONSE = 0;
-}
-
-
-/**
- * HTTP parser which parses the HTTP stream as data is supplied
- * through the [:writeList:] and [:connectionClosed:] methods. As the
- * data is parsed the following callbacks are called:
- *
- * [:requestStart:]
- * [:responseStart:]
- * [:headerReceived:]
- * [:headersComplete:]
- * [:dataReceived:]
- * [:dataEnd:]
- * [:error:]
- *
- * If an HTTP parser error occours it is possible to get an exception
- * thrown from the [:writeList:] and [:connectionClosed:] methods if
- * the error callback is not set.
- *
- * The connection upgrades (e.g. switching from HTTP/1.1 to the
- * WebSocket protocol) is handled in a special way. If connection
- * upgrade is specified in the headers, then on the callback to
- * [:headersComplete:] the [:upgrade:] property on the [:HttpParser:]
- * object will be [:true:] indicating that from now on the protocol is
- * not HTTP anymore and no more callbacks will happen, that is
- * [:dataReceived:] and [:dataEnd:] are not called in this case as
- * there is no more HTTP data. After the upgrade the call to
- * [:writeList:] causing the upgrade will return with the number of
- * bytes parsed as HTTP. Any unparsed bytes is part of the protocol
- * the connection is upgrading to and should be handled according to
- * that protocol.
- */
-class _HttpParser {
- _HttpParser() {
- _reset();
- }
-
- // From RFC 2616.
- // generic-message = start-line
- // *(message-header CRLF)
- // CRLF
- // [ message-body ]
- // start-line = Request-Line | Status-Line
- // Request-Line = Method SP Request-URI SP HTTP-Version CRLF
- // Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF
- // message-header = field-name ":" [ field-value ]
- int writeList(List<int> buffer, int offset, int count) {
- int index = offset;
- int lastIndex = offset + count;
- try {
- if (_state == _State.CLOSED) {
- throw new HttpParserException("Data on closed connection");
- }
- if (_state == _State.UPGRADED) {
- throw new HttpParserException("Data on upgraded connection");
- }
- if (_state == _State.FAILURE) {
- throw new HttpParserException("Data on failed connection");
- }
- while ((index < lastIndex) &&
- _state != _State.FAILURE &&
- _state != _State.UPGRADED) {
- int byte = buffer[index];
- switch (_state) {
- case _State.START:
- if (byte == _Const.HTTP[0]) {
- // Start parsing method or HTTP version.
- _httpVersionIndex = 1;
- _state = _State.METHOD_OR_RESPONSE_HTTP_VERSION;
- } else {
- // Start parsing method.
- if (!_isTokenChar(byte)) {
- throw new HttpParserException("Invalid request method");
- }
- _method_or_status_code.addCharCode(byte);
- _state = _State.REQUEST_LINE_METHOD;
- }
- break;
-
- case _State.METHOD_OR_RESPONSE_HTTP_VERSION:
- if (_httpVersionIndex < _Const.HTTP.length &&
- byte == _Const.HTTP[_httpVersionIndex]) {
- // Continue parsing HTTP version.
- _httpVersionIndex++;
- } else if (_httpVersionIndex == _Const.HTTP.length &&
- byte == _CharCode.SLASH) {
- // HTTP/ parsed. As method is a token this cannot be a
- // method anymore.
- _httpVersionIndex++;
- _state = _State.RESPONSE_HTTP_VERSION;
- } else {
- // Did not parse HTTP version. Expect method instead.
- for (int i = 0; i < _httpVersionIndex; i++) {
- _method_or_status_code.addCharCode(_Const.HTTP[i]);
- }
- if (byte == _CharCode.SP) {
- _state = _State.REQUEST_LINE_URI;
- } else {
- _method_or_status_code.addCharCode(byte);
- _httpVersion = _HttpVersion.UNDETERMINED;
- _state = _State.REQUEST_LINE_METHOD;
- }
- }
- break;
-
- case _State.RESPONSE_HTTP_VERSION:
- if (_httpVersionIndex < _Const.HTTP1DOT.length) {
- // Continue parsing HTTP version.
- _expect(byte, _Const.HTTP1DOT[_httpVersionIndex]);
- _httpVersionIndex++;
- } else if (_httpVersionIndex == _Const.HTTP1DOT.length &&
- byte == _CharCode.ONE) {
- // HTTP/1.1 parsed.
- _httpVersion = _HttpVersion.HTTP11;
- _persistentConnection = true;
- _httpVersionIndex++;
- } else if (_httpVersionIndex == _Const.HTTP1DOT.length &&
- byte == _CharCode.ZERO) {
- // HTTP/1.0 parsed.
- _httpVersion = _HttpVersion.HTTP10;
- _persistentConnection = false;
- _httpVersionIndex++;
- } else if (_httpVersionIndex == _Const.HTTP1DOT.length + 1) {
- _expect(byte, _CharCode.SP);
- // HTTP version parsed.
- _state = _State.RESPONSE_LINE_STATUS_CODE;
- } else {
- throw new HttpParserException("Invalid response line");
- }
- break;
-
- case _State.REQUEST_LINE_METHOD:
- if (byte == _CharCode.SP) {
- _state = _State.REQUEST_LINE_URI;
- } else {
- if (_Const.SEPARATORS_AND_CR_LF.indexOf(byte) != -1) {
- throw new HttpParserException("Invalid request method");
- }
- _method_or_status_code.addCharCode(byte);
- }
- break;
-
- case _State.REQUEST_LINE_URI:
- if (byte == _CharCode.SP) {
- if (_uri_or_reason_phrase.length == 0) {
- throw new HttpParserException("Invalid request URI");
- }
- _state = _State.REQUEST_LINE_HTTP_VERSION;
- _httpVersionIndex = 0;
- } else {
- if (byte == _CharCode.CR || byte == _CharCode.LF) {
- throw new HttpParserException("Invalid request URI");
- }
- _uri_or_reason_phrase.addCharCode(byte);
- }
- break;
-
- case _State.REQUEST_LINE_HTTP_VERSION:
- if (_httpVersionIndex < _Const.HTTP1DOT.length) {
- _expect(byte, _Const.HTTP11[_httpVersionIndex]);
- _httpVersionIndex++;
- } else if (_httpVersionIndex == _Const.HTTP1DOT.length) {
- if (byte == _CharCode.ONE) {
- // HTTP/1.1 parsed.
- _httpVersion = _HttpVersion.HTTP11;
- _persistentConnection = true;
- _httpVersionIndex++;
- } else if (byte == _CharCode.ZERO) {
- // HTTP/1.0 parsed.
- _httpVersion = _HttpVersion.HTTP10;
- _persistentConnection = false;
- _httpVersionIndex++;
- } else {
- throw new HttpParserException("Invalid response line");
- }
- } else {
- _expect(byte, _CharCode.CR);
- _state = _State.REQUEST_LINE_ENDING;
- }
- break;
-
- case _State.REQUEST_LINE_ENDING:
- _expect(byte, _CharCode.LF);
- _messageType = _MessageType.REQUEST;
- if (requestStart != null) {
- requestStart(_method_or_status_code.toString(),
- _uri_or_reason_phrase.toString(),
- version);
- }
- _method_or_status_code.clear();
- _uri_or_reason_phrase.clear();
- _state = _State.HEADER_START;
- break;
-
- case _State.RESPONSE_LINE_STATUS_CODE:
- if (byte == _CharCode.SP) {
- if (_method_or_status_code.length != 3) {
- throw new HttpParserException("Invalid response status code");
- }
- _state = _State.RESPONSE_LINE_REASON_PHRASE;
- } else {
- if (byte < 0x30 && 0x39 < byte) {
- throw new HttpParserException("Invalid response status code");
- } else {
- _method_or_status_code.addCharCode(byte);
- }
- }
- break;
-
- case _State.RESPONSE_LINE_REASON_PHRASE:
- if (byte == _CharCode.CR) {
- if (_uri_or_reason_phrase.length == 0) {
- throw new HttpParserException("Invalid response reason phrase");
- }
- _state = _State.RESPONSE_LINE_ENDING;
- } else {
- if (byte == _CharCode.CR || byte == _CharCode.LF) {
- throw new HttpParserException("Invalid response reason phrase");
- }
- _uri_or_reason_phrase.addCharCode(byte);
- }
- break;
-
- case _State.RESPONSE_LINE_ENDING:
- _expect(byte, _CharCode.LF);
- _messageType == _MessageType.RESPONSE;
- int statusCode = parseInt(_method_or_status_code.toString());
- if (statusCode < 100 || statusCode > 599) {
- throw new HttpParserException("Invalid response status code");
- } else {
- // Check whether this response will never have a body.
- _noMessageBody =
- statusCode <= 199 || statusCode == 204 || statusCode == 304;
- }
- if (responseStart != null) {
- responseStart(statusCode, _uri_or_reason_phrase.toString(), version);
- }
- _method_or_status_code.clear();
- _uri_or_reason_phrase.clear();
- _state = _State.HEADER_START;
- break;
-
- case _State.HEADER_START:
- if (byte == _CharCode.CR) {
- _state = _State.HEADER_ENDING;
- } else {
- // Start of new header field.
- _headerField.addCharCode(_toLowerCase(byte));
- _state = _State.HEADER_FIELD;
- }
- break;
-
- case _State.HEADER_FIELD:
- if (byte == _CharCode.COLON) {
- _state = _State.HEADER_VALUE_START;
- } else {
- if (!_isTokenChar(byte)) {
- throw new HttpParserException("Invalid header field name");
- }
- _headerField.addCharCode(_toLowerCase(byte));
- }
- break;
-
- case _State.HEADER_VALUE_START:
- if (byte == _CharCode.CR) {
- _state = _State.HEADER_VALUE_FOLDING_OR_ENDING;
- } else if (byte != _CharCode.SP && byte != _CharCode.HT) {
- // Start of new header value.
- _headerValue.addCharCode(byte);
- _state = _State.HEADER_VALUE;
- }
- break;
-
- case _State.HEADER_VALUE:
- if (byte == _CharCode.CR) {
- _state = _State.HEADER_VALUE_FOLDING_OR_ENDING;
- } else {
- _headerValue.addCharCode(byte);
- }
- break;
-
- case _State.HEADER_VALUE_FOLDING_OR_ENDING:
- _expect(byte, _CharCode.LF);
- _state = _State.HEADER_VALUE_FOLD_OR_END;
- break;
-
- case _State.HEADER_VALUE_FOLD_OR_END:
- if (byte == _CharCode.SP || byte == _CharCode.HT) {
- _state = _State.HEADER_VALUE_START;
- } else {
- String headerField = _headerField.toString();
- String headerValue =_headerValue.toString();
- bool reportHeader = true;
- if (headerField == "content-length" && !_chunked) {
- // Ignore the Content-Length header if Transfer-Encoding
- // is chunked (RFC 2616 section 4.4)
- _contentLength = parseInt(headerValue);
- } else if (headerField == "connection") {
- List<String> tokens = _tokenizeFieldValue(headerValue);
- for (int i = 0; i < tokens.length; i++) {
- String token = tokens[i].toLowerCase();
- if (token == "keep-alive") {
- _persistentConnection = true;
- } else if (token == "close") {
- _persistentConnection = false;
- } else if (token == "upgrade") {
- _connectionUpgrade = true;
- }
- if (headerReceived != null) {
- headerReceived(headerField, token);
- }
- }
- reportHeader = false;
- } else if (headerField == "transfer-encoding" &&
- headerValue.toLowerCase() == "chunked") {
- // Ignore the Content-Length header if Transfer-Encoding
- // is chunked (RFC 2616 section 4.4)
- _chunked = true;
- _contentLength = -1;
- }
- if (reportHeader && headerReceived != null) {
- headerReceived(headerField, headerValue);
- }
- _headerField.clear();
- _headerValue.clear();
-
- if (byte == _CharCode.CR) {
- _state = _State.HEADER_ENDING;
- } else {
- // Start of new header field.
- _headerField.addCharCode(_toLowerCase(byte));
- _state = _State.HEADER_FIELD;
- }
- }
- break;
-
- case _State.HEADER_ENDING:
- _expect(byte, _CharCode.LF);
- // 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 &&
- _contentLength < 0 &&
- _chunked == false) {
- _contentLength = 0;
- }
- if (_connectionUpgrade) {
- _state = _State.UPGRADED;
- _unparsedData =
- buffer.getRange(index + 1, count - (index + 1 - offset));
- if (headersComplete != null) headersComplete();
- } else {
- if (headersComplete != null) headersComplete();
- if (_chunked) {
- _state = _State.CHUNK_SIZE;
- _remainingContent = 0;
- } else if (_contentLength == 0 ||
- (_messageType == _MessageType.RESPONSE &&
- (_noMessageBody || _responseToMethod == "HEAD"))) {
- // If there is no message body get ready to process the
- // next request.
- _bodyEnd();
- _reset();
- } else if (_contentLength > 0) {
- _remainingContent = _contentLength;
- _state = _State.BODY;
- } else {
- // Neither chunked nor content length. End of body
- // indicated by close.
- _state = _State.BODY;
- }
- }
- break;
-
- case _State.CHUNK_SIZE_STARTING_CR:
- _expect(byte, _CharCode.CR);
- _state = _State.CHUNK_SIZE_STARTING_LF;
- break;
-
- case _State.CHUNK_SIZE_STARTING_LF:
- _expect(byte, _CharCode.LF);
- _state = _State.CHUNK_SIZE;
- break;
-
- case _State.CHUNK_SIZE:
- if (byte == _CharCode.CR) {
- _state = _State.CHUNK_SIZE_ENDING;
- } else if (byte == _CharCode.SEMI_COLON) {
- _state = _State.CHUNK_SIZE_EXTENSION;
- } else {
- int value = _expectHexDigit(byte);
- _remainingContent = _remainingContent * 16 + value;
- }
- break;
-
- case _State.CHUNK_SIZE_EXTENSION:
- if (byte == _CharCode.CR) {
- _state = _State.CHUNK_SIZE_ENDING;
- }
- break;
-
- case _State.CHUNK_SIZE_ENDING:
- _expect(byte, _CharCode.LF);
- if (_remainingContent > 0) {
- _state = _State.BODY;
- } else {
- _state = _State.CHUNKED_BODY_DONE_CR;
- }
- break;
-
- case _State.CHUNKED_BODY_DONE_CR:
- _expect(byte, _CharCode.CR);
- _state = _State.CHUNKED_BODY_DONE_LF;
- break;
-
- case _State.CHUNKED_BODY_DONE_LF:
- _expect(byte, _CharCode.LF);
- _bodyEnd();
- _reset();
- break;
-
- case _State.BODY:
- // The body is not handled one byte at a time but in blocks.
- int dataAvailable = lastIndex - index;
- List<int> data;
- if (_remainingContent == null ||
- dataAvailable <= _remainingContent) {
- data = new Uint8List(dataAvailable);
- data.setRange(0, dataAvailable, buffer, index);
- } else {
- data = new Uint8List(_remainingContent);
- data.setRange(0, _remainingContent, buffer, index);
- }
-
- if (dataReceived != null) dataReceived(data);
- if (_remainingContent != null) {
- _remainingContent -= data.length;
- }
- index += data.length;
- if (_remainingContent == 0) {
- if (!_chunked) {
- _bodyEnd();
- _reset();
- } else {
- _state = _State.CHUNK_SIZE_STARTING_CR;
- }
- }
-
- // Hack - as we always do index++ below.
- index--;
- break;
-
- case _State.FAILURE:
- // Should be unreachable.
- assert(false);
- break;
-
- default:
- // Should be unreachable.
- assert(false);
- break;
- }
-
- // Move to the next byte.
- index++;
- }
- } catch (e) {
- // Report the error through the error callback if any. Otherwise
- // throw the error.
- if (error != null) {
- error(e);
- _state = _State.FAILURE;
- } else {
- throw e;
- }
- }
-
- // Return the number of bytes parsed.
- return index - offset;
- }
-
- void connectionClosed() {
- if (_state < _State.FIRST_BODY_STATE) {
- _state = _State.FAILURE;
- // Report the error through the error callback if any. Otherwise
- // throw the error.
- var e = new HttpParserException(
- "Connection closed before full header was received");
- if (error != null) {
- error(e);
- return;
- }
- throw e;
- }
-
- if (!_chunked && _contentLength == -1) {
- if (_state != _State.START) {
- if (dataEnd != null) dataEnd(true);
- }
- _state = _State.CLOSED;
- } else {
- _state = _State.FAILURE;
- // Report the error through the error callback if any. Otherwise
- // throw the error.
- var e = new HttpParserException(
- "Connection closed before full body was received");
- if (error != null) {
- error(e);
- return;
- }
- throw e;
- }
- }
-
- String get version {
- switch (_httpVersion) {
- case _HttpVersion.HTTP10:
- return "1.0";
- case _HttpVersion.HTTP11:
- return "1.1";
- }
- return null;
- }
-
- int get messageType => _messageType;
- int get contentLength => _contentLength;
- bool get upgrade => _connectionUpgrade && _state == _State.UPGRADED;
- bool get persistentConnection => _persistentConnection;
-
- void set responseToMethod(String method) { _responseToMethod = method; }
-
- bool get isIdle => _state == _State.START;
-
- List<int> get unparsedData => _unparsedData;
-
- void _bodyEnd() {
- if (dataEnd != null) {
- dataEnd(_messageType == _MessageType.RESPONSE && !_persistentConnection);
- }
- }
-
- _reset() {
- _state = _State.START;
- _messageType = _MessageType.UNDETERMINED;
- _headerField = new StringBuffer();
- _headerValue = new StringBuffer();
- _method_or_status_code = new StringBuffer();
- _uri_or_reason_phrase = new StringBuffer();
-
- _httpVersion = _HttpVersion.UNDETERMINED;
- _contentLength = -1;
- _persistentConnection = false;
- _connectionUpgrade = false;
- _chunked = false;
-
- _noMessageBody = false;
- _responseToMethod = null;
- _remainingContent = null;
- }
-
- bool _isTokenChar(int byte) {
- return byte > 31 && byte < 128 && _Const.SEPARATORS.indexOf(byte) == -1;
- }
-
- List<String> _tokenizeFieldValue(String headerValue) {
- List<String> tokens = new List<String>();
- int start = 0;
- int index = 0;
- while (index < headerValue.length) {
- if (headerValue[index] == ",") {
- tokens.add(headerValue.substring(start, index));
- start = index + 1;
- } else if (headerValue[index] == " " || headerValue[index] == "\t") {
- start++;
- }
- index++;
- }
- tokens.add(headerValue.substring(start, index));
- return tokens;
- }
-
- int _toLowerCase(int byte) {
- final int aCode = "A".charCodeAt(0);
- final int zCode = "Z".charCodeAt(0);
- final int delta = "a".charCodeAt(0) - aCode;
- return (aCode <= byte && byte <= zCode) ? byte + delta : byte;
- }
-
- int _expect(int val1, int val2) {
- if (val1 != val2) {
- throw new HttpParserException("Failed to parse HTTP");
- }
- }
-
- int _expectHexDigit(int byte) {
- if (0x30 <= byte && byte <= 0x39) {
- return byte - 0x30; // 0 - 9
- } else if (0x41 <= byte && byte <= 0x46) {
- return byte - 0x41 + 10; // A - F
- } else if (0x61 <= byte && byte <= 0x66) {
- return byte - 0x61 + 10; // a - f
- } else {
- throw new HttpParserException("Failed to parse HTTP");
- }
- }
-
- int _state;
- int _httpVersionIndex;
- int _messageType;
- StringBuffer _method_or_status_code;
- StringBuffer _uri_or_reason_phrase;
- StringBuffer _headerField;
- StringBuffer _headerValue;
-
- int _httpVersion;
- int _contentLength;
- bool _persistentConnection;
- bool _connectionUpgrade;
- bool _chunked;
-
- bool _noMessageBody;
- String _responseToMethod; // Indicates the method used for the request.
- int _remainingContent;
-
- List<int> _unparsedData; // Unparsed data after connection upgrade.
- // Callbacks.
- Function requestStart;
- Function responseStart;
- Function headerReceived;
- Function headersComplete;
- Function dataReceived;
- Function dataEnd;
- Function error;
-}
-
-
-class HttpParserException implements Exception {
- const HttpParserException([String this.message = ""]);
- String toString() => "HttpParserException: $message";
- final String message;
-}

Powered by Google App Engine
This is Rietveld 408576698