mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 12:24:24 +00:00
Slightly speed up http-parser and http-header-writing.
BUG= R=sgjesse@google.com Review URL: https://codereview.chromium.org//173683002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@32850 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
parent
9635777fe0
commit
04c6eca951
3 changed files with 54 additions and 39 deletions
|
@ -396,25 +396,31 @@ class _HttpHeaders implements HttpHeaders {
|
|||
}
|
||||
|
||||
// Format headers.
|
||||
_headers.forEach((String name, List<String> values) {
|
||||
for (String name in _headers.keys) {
|
||||
List<String> values = _headers[name];
|
||||
bool fold = _foldHeader(name);
|
||||
var nameData = name.codeUnits;
|
||||
write(nameData);
|
||||
write(const [_CharCode.COLON, _CharCode.SP]);
|
||||
buffer[offset++] = _CharCode.COLON;
|
||||
buffer[offset++] = _CharCode.SP;
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
if (i > 0) {
|
||||
if (fold) {
|
||||
write(const [_CharCode.COMMA, _CharCode.SP]);
|
||||
buffer[offset++] = _CharCode.COMMA;
|
||||
buffer[offset++] = _CharCode.SP;
|
||||
} else {
|
||||
write(const [_CharCode.CR, _CharCode.LF]);
|
||||
buffer[offset++] = _CharCode.CR;
|
||||
buffer[offset++] = _CharCode.LF;
|
||||
write(nameData);
|
||||
write(const [_CharCode.COLON, _CharCode.SP]);
|
||||
buffer[offset++] = _CharCode.COLON;
|
||||
buffer[offset++] = _CharCode.SP;
|
||||
}
|
||||
}
|
||||
write(values[i].codeUnits);
|
||||
}
|
||||
write(const [_CharCode.CR, _CharCode.LF]);
|
||||
});
|
||||
buffer[offset++] = _CharCode.CR;
|
||||
buffer[offset++] = _CharCode.LF;
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
|
|
@ -1333,7 +1333,7 @@ class _HttpClientConnection {
|
|||
}
|
||||
// Start sending the request (lazy, delayed until the user provides
|
||||
// data).
|
||||
_httpParser.responseToMethod = method;
|
||||
_httpParser.isHead = method == "HEAD";
|
||||
_streamFuture = outgoing.done
|
||||
.then((s) {
|
||||
// Request sent, set up response completer.
|
||||
|
|
|
@ -247,10 +247,11 @@ 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;
|
||||
int _statusCodeLength = 0;
|
||||
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 +259,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 +374,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 +399,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 +449,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,19 +500,17 @@ 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
|
||||
// \r\n right after the status code.
|
||||
_state = _State.RESPONSE_LINE_ENDING;
|
||||
} else {
|
||||
if (byte < 0x30 && 0x39 < byte) {
|
||||
_statusCodeLength++;
|
||||
if ((byte < 0x30 && 0x39 < byte) || _statusCodeLength > 3) {
|
||||
throw new HttpException("Invalid response status code");
|
||||
} else {
|
||||
_method_or_status_code.add(byte);
|
||||
_statusCode = _statusCode * 10 + byte - 0x30;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -531,14 +529,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 +593,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 +645,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 +654,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 +665,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 +864,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,12 +887,13 @@ 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;
|
||||
_statusCodeLength = 0;
|
||||
|
||||
_httpVersion = _HttpVersion.UNDETERMINED;
|
||||
_transferLength = -1;
|
||||
|
@ -901,7 +902,6 @@ class _HttpParser extends Stream<_HttpIncoming> {
|
|||
_chunked = false;
|
||||
|
||||
_noMessageBody = false;
|
||||
_responseToMethod = null;
|
||||
_remainingContent = -1;
|
||||
|
||||
_headers = null;
|
||||
|
@ -940,6 +940,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");
|
||||
|
|
Loading…
Reference in a new issue