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

Unified Diff: runtime/bin/http_impl.dart

Issue 9581011: Make the HttpParser and HttpUtil classes private (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 10 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 | runtime/bin/http_parser.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/bin/http_impl.dart
diff --git a/runtime/bin/http_impl.dart b/runtime/bin/http_impl.dart
index 1cad3472760f4079699cee8c8682d9701251302e..84798d7c2796de096e165c5904048fe922dfa1a1 100644
--- a/runtime/bin/http_impl.dart
+++ b/runtime/bin/http_impl.dart
@@ -2,419 +2,6 @@
// 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/1.0".
- static final HTTP10 = const [72, 84, 84, 80, 47, 49, 46, 48];
- // Bytes for "HTTP/1.1".
- static final HTTP11 = const [72, 84, 84, 80, 47, 49, 46, 49];
-
- static final END_CHUNKED = const [0x30, 13, 10, 13, 10];
-}
-
-// Frequently used character codes.
-class _CharCode {
- static final int HT = 9;
- static final int LF = 10;
- static final int CR = 13;
- static final int SP = 32;
- static final int COLON = 58;
-}
-
-
-// States of the HTTP parser state machine.
-class _State {
- static final int START = 0;
- static final int METHOD_OR_HTTP_VERSION = 1;
- static final int REQUEST_LINE_METHOD = 2;
- static final int REQUEST_LINE_URI = 3;
- static final int REQUEST_LINE_HTTP_VERSION = 4;
- static final int REQUEST_LINE_ENDING = 5;
- static final int RESPONSE_LINE_STATUS_CODE = 6;
- static final int RESPONSE_LINE_REASON_PHRASE = 7;
- static final int RESPONSE_LINE_ENDING = 8;
- static final int HEADER_START = 9;
- static final int HEADER_FIELD = 10;
- static final int HEADER_VALUE_START = 11;
- static final int HEADER_VALUE = 12;
- static final int HEADER_VALUE_FOLDING_OR_ENDING = 13;
- static final int HEADER_VALUE_FOLD_OR_END = 14;
- static final int HEADER_ENDING = 15;
- static final int CHUNK_SIZE_STARTING_CR = 16;
- static final int CHUNK_SIZE_STARTING_LF = 17;
- static final int CHUNK_SIZE = 18;
- static final int CHUNK_SIZE_ENDING = 19;
- static final int CHUNKED_BODY_DONE_CR = 20;
- static final int CHUNKED_BODY_DONE_LF = 21;
- static final int BODY = 22;
-}
-
-
-/**
- * HTTP parser which parses the HTTP stream as data is supplied
- * through the writeList method. As the data is parsed the events
- * RequestStart
- * UriReceived
- * HeaderReceived
- * HeadersComplete
- * DataReceived
- * DataEnd
- * are generated.
- * Currently only HTTP requests with Content-Length header are supported.
- */
-class HttpParser {
- HttpParser()
- : _state = _State.START,
- _failure = false,
- _headerField = new StringBuffer(),
- _headerValue = new StringBuffer(),
- _method_or_status_code = new StringBuffer(),
- _uri_or_reason_phrase = new StringBuffer();
-
- // 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;
- while ((index < lastIndex) && !_failure) {
- int byte = buffer[index];
- switch (_state) {
- case _State.START:
- _contentLength = 0;
- _keepAlive = false;
- _chunked = false;
-
- if (byte == _Const.HTTP11[0]) {
- // Start parsing HTTP method.
- _httpVersionIndex = 1;
- _state = _State.METHOD_OR_HTTP_VERSION;
- } else {
- // Start parsing method.
- _method_or_status_code.addCharCode(byte);
- _state = _State.REQUEST_LINE_METHOD;
- }
- break;
-
- case _State.METHOD_OR_HTTP_VERSION:
- if (_httpVersionIndex < _Const.HTTP11.length &&
- byte == _Const.HTTP11[_httpVersionIndex]) {
- // Continue parsing HTTP version.
- _httpVersionIndex++;
- } else if (_httpVersionIndex == _Const.HTTP11.length &&
- byte == _CharCode.SP) {
- // HTTP version parsed.
- _state = _State.RESPONSE_LINE_STATUS_CODE;
- } else {
- // Did not parse HTTP version. Expect method instead.
- for (int i = 0; i < _httpVersionIndex; i++) {
- _method_or_status_code.addCharCode(_Const.HTTP11[i]);
- }
- _state = _State.REQUEST_LINE_URI;
- }
- break;
-
- case _State.REQUEST_LINE_METHOD:
- if (byte == _CharCode.SP) {
- _state = _State.REQUEST_LINE_URI;
- } else {
- _method_or_status_code.addCharCode(byte);
- }
- break;
-
- case _State.REQUEST_LINE_URI:
- if (byte == _CharCode.SP) {
- _state = _State.REQUEST_LINE_HTTP_VERSION;
- _httpVersionIndex = 0;
- } else {
- _uri_or_reason_phrase.addCharCode(byte);
- }
- break;
-
- case _State.REQUEST_LINE_HTTP_VERSION:
- if (_httpVersionIndex < _Const.HTTP11.length) {
- _expect(byte, _Const.HTTP11[_httpVersionIndex]);
- _httpVersionIndex++;
- } else {
- _expect(byte, _CharCode.CR);
- _state = _State.REQUEST_LINE_ENDING;
- }
- break;
-
- case _State.REQUEST_LINE_ENDING:
- _expect(byte, _CharCode.LF);
- if (requestStart != null) {
- requestStart(_method_or_status_code.toString(),
- _uri_or_reason_phrase.toString());
- }
- _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) {
- _state = _State.RESPONSE_LINE_REASON_PHRASE;
- } else {
- if (byte < 0x30 && 0x39 < byte) {
- _failure = true;
- } else {
- _method_or_status_code.addCharCode(byte);
- }
- }
- break;
-
- case _State.RESPONSE_LINE_REASON_PHRASE:
- if (byte == _CharCode.CR) {
- _state = _State.RESPONSE_LINE_ENDING;
- } else {
- _uri_or_reason_phrase.addCharCode(byte);
- }
- break;
-
- case _State.RESPONSE_LINE_ENDING:
- _expect(byte, _CharCode.LF);
- // TODO(sgjesse): Check for valid status code.
- if (responseStart != null) {
- responseStart(Math.parseInt(_method_or_status_code.toString()),
- _uri_or_reason_phrase.toString());
- }
- _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 {
- _headerField.addCharCode(_toLowerCase(byte));
- }
- break;
-
- case _State.HEADER_VALUE_START:
- 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();
- // Ignore the Content-Length header if Transfer-Encoding
- // is chunked (RFC 2616 section 4.4)
- if (headerField == "content-length" && !_chunked) {
- _contentLength = Math.parseInt(headerValue);
- } else if (headerField == "connection" &&
- headerValue == "keep-alive") {
- _keepAlive = true;
- } else if (headerField == "transfer-encoding" &&
- headerValue == "chunked") {
- _chunked = true;
- _contentLength = -1;
- }
- if (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 (headersComplete != null) headersComplete();
-
- // If there is no data get ready to process the next request.
- if (_chunked) {
- _state = _State.CHUNK_SIZE;
- _remainingContent = 0;
- } else if (_contentLength == 0) {
- if (dataEnd != null) dataEnd();
- _state = _State.START;
- } else if (_contentLength > 0) {
- _remainingContent = _contentLength;
- _state = _State.BODY;
- } else {
- // TODO(sgjesse): Error handling.
- }
- 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 {
- int value = _expectHexDigit(byte);
- _remainingContent = _remainingContent * 16 + value;
- }
- 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);
- if (dataEnd != null) dataEnd();
- _state = _State.START;
- break;
-
- case _State.BODY:
- // The body is not handled one byte at the time but in blocks.
- int dataAvailable = lastIndex - index;
- ByteArray data;
- if (dataAvailable <= _remainingContent) {
- data = new ByteArray(dataAvailable);
- data.setRange(0, dataAvailable, buffer, index);
- } else {
- data = new ByteArray(_remainingContent);
- data.setRange(0, _remainingContent, buffer, index);
- }
-
- if (dataReceived != null) dataReceived(data);
- _remainingContent -= data.length;
- index += data.length;
- if (_remainingContent == 0) {
- if (!_chunked) {
- if (dataEnd != null) dataEnd();
- _state = _State.START;
- } else {
- _state = _State.CHUNK_SIZE_STARTING_CR;
- }
- }
-
- // Hack - as we always do index++ below.
- index--;
- break;
-
- default:
- // Should be unreachable.
- assert(false);
- }
-
- // Move to the next byte.
- index++;
- }
-
- // Return the number of bytes parsed.
- return index - offset;
- }
-
- int get contentLength() => _contentLength;
- bool get keepAlive() => _keepAlive;
-
- 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) {
- _failure = true;
- }
- }
-
- 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 {
- _failure = true;
- return 0;
- }
- }
-
- int _state;
- bool _failure;
- int _httpVersionIndex;
- StringBuffer _method_or_status_code;
- StringBuffer _uri_or_reason_phrase;
- StringBuffer _headerField;
- StringBuffer _headerValue;
-
- int _contentLength;
- bool _keepAlive;
- bool _chunked;
-
- int _remainingContent;
-
- // Callbacks.
- Function requestStart;
- Function responseStart;
- Function headerReceived;
- Function headersComplete;
- Function dataReceived;
- Function dataEnd;
-}
-
-
// Utility class for encoding a string into UTF-8 byte stream.
class _UTF8Encoder {
static List<int> encodeString(String string) {
@@ -626,13 +213,13 @@ class _HttpRequest extends _HttpRequestResponseBase implements HttpRequest {
int position;
position = uri.indexOf("?", 0);
if (position == -1) {
- _path = HttpUtil.decodeUrlEncodedString(_uri);
+ _path = _HttpUtils.decodeUrlEncodedString(_uri);
_queryString = null;
_queryParameters = new Map();
} else {
- _path = HttpUtil.decodeUrlEncodedString(_uri.substring(0, position));
+ _path = _HttpUtils.decodeUrlEncodedString(_uri.substring(0, position));
_queryString = _uri.substring(position + 1);
- _queryParameters = HttpUtil.splitQueryString(_queryString);
+ _queryParameters = _HttpUtils.splitQueryString(_queryString);
}
}
@@ -919,7 +506,7 @@ class _HttpOutputStream implements OutputStream {
class _HttpConnectionBase {
_HttpConnectionBase() : _sendBuffers = new Queue(),
- _httpParser = new HttpParser();
+ _httpParser = new _HttpParser();
void _connectionEstablished(Socket socket) {
_socket = socket;
@@ -975,7 +562,7 @@ class _HttpConnectionBase {
Socket _socket;
bool _closing = false; // Is the socket closed by the client?
- HttpParser _httpParser;
+ _HttpParser _httpParser;
Queue _sendBuffers;
@@ -1515,63 +1102,3 @@ class _HttpClient implements HttpClient {
Timer _evictionTimer;
bool _shutdown; // Has this HTTP client been shutdown?
}
-
-
-class HttpUtil {
- static String decodeUrlEncodedString(String urlEncoded) {
- void invalidEscape() {
- // TODO(sgjesse): Handle the error.
- }
-
- StringBuffer result = new StringBuffer();
- for (int ii = 0; urlEncoded.length > ii; ++ii) {
- if ('+' == urlEncoded[ii]) {
- result.add(' ');
- } else if ('%' == urlEncoded[ii] &&
- urlEncoded.length - 2 > ii) {
- try {
- int charCode =
- Math.parseInt('0x' + urlEncoded.substring(ii + 1, ii + 3));
- if (charCode <= 0x7f) {
- result.add(new String.fromCharCodes([charCode]));
- ii += 2;
- } else {
- invalidEscape();
- return '';
- }
- } catch (BadNumberFormatException ignored) {
- invalidEscape();
- return '';
- }
- } else {
- result.add(urlEncoded[ii]);
- }
- }
- return result.toString();
- }
-
- static Map<String, String> splitQueryString(String queryString) {
- Map<String, String> result = new Map<String, String>();
- int currentPosition = 0;
- while (currentPosition < queryString.length) {
- int position = queryString.indexOf("=", currentPosition);
- if (position == -1) {
- break;
- }
- String name = queryString.substring(currentPosition, position);
- currentPosition = position + 1;
- position = queryString.indexOf("&", currentPosition);
- String value;
- if (position == -1) {
- value = queryString.substring(currentPosition);
- currentPosition = queryString.length;
- } else {
- value = queryString.substring(currentPosition, position);
- currentPosition = position + 1;
- }
- result[HttpUtil.decodeUrlEncodedString(name)] =
- HttpUtil.decodeUrlEncodedString(value);
- }
- return result;
- }
-}
« no previous file with comments | « no previous file | runtime/bin/http_parser.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698