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

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

Issue 11415027: Refactor the HTTP parser to collect headers (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Addessed review comments Created 8 years, 1 month 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 | sdk/lib/io/http_parser.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sdk/lib/io/http_impl.dart
diff --git a/sdk/lib/io/http_impl.dart b/sdk/lib/io/http_impl.dart
index e61fcc28626da13167c9a1648d6335d9ebaf68d9..fc69108579c0a95e86f0ba3ef153916f4f40b47f 100644
--- a/sdk/lib/io/http_impl.dart
+++ b/sdk/lib/io/http_impl.dart
@@ -2,632 +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.
-class _HttpHeaders implements HttpHeaders {
- _HttpHeaders() : _headers = new Map<String, List<String>>();
-
- List<String> operator[](String name) {
- name = name.toLowerCase();
- return _headers[name];
- }
-
- String value(String name) {
- name = name.toLowerCase();
- List<String> values = _headers[name];
- if (values == null) return null;
- if (values.length > 1) {
- throw new HttpException("More than one value for header $name");
- }
- return values[0];
- }
-
- void add(String name, Object value) {
- _checkMutable();
- if (value is List) {
- for (int i = 0; i < value.length; i++) {
- _add(name, value[i]);
- }
- } else {
- _add(name, value);
- }
- }
-
- void set(String name, Object value) {
- name = name.toLowerCase();
- _checkMutable();
- removeAll(name);
- add(name, value);
- }
-
- void remove(String name, Object value) {
- _checkMutable();
- name = name.toLowerCase();
- List<String> values = _headers[name];
- if (values != null) {
- int index = values.indexOf(value);
- if (index != -1) {
- values.removeRange(index, 1);
- }
- }
- }
-
- void removeAll(String name) {
- _checkMutable();
- name = name.toLowerCase();
- _headers.remove(name);
- }
-
- void forEach(void f(String name, List<String> values)) {
- _headers.forEach(f);
- }
-
- void noFolding(String name) {
- if (_noFoldingHeaders == null) _noFoldingHeaders = new List<String>();
- _noFoldingHeaders.add(name);
- }
-
- String get host => _host;
-
- void set host(String host) {
- _checkMutable();
- _host = host;
- _updateHostHeader();
- }
-
- int get port => _port;
-
- void set port(int port) {
- _checkMutable();
- _port = port;
- _updateHostHeader();
- }
-
- Date get ifModifiedSince {
- List<String> values = _headers["if-modified-since"];
- if (values != null) {
- try {
- return _HttpUtils.parseDate(values[0]);
- } on Exception catch (e) {
- return null;
- }
- }
- return null;
- }
-
- void set ifModifiedSince(Date ifModifiedSince) {
- _checkMutable();
- // Format "ifModifiedSince" header with date in Greenwich Mean Time (GMT).
- String formatted = _HttpUtils.formatDate(ifModifiedSince.toUtc());
- _set("if-modified-since", formatted);
- }
-
- Date get date {
- List<String> values = _headers["date"];
- if (values != null) {
- try {
- return _HttpUtils.parseDate(values[0]);
- } on Exception catch (e) {
- return null;
- }
- }
- return null;
- }
-
- void set date(Date date) {
- _checkMutable();
- // Format "Date" header with date in Greenwich Mean Time (GMT).
- String formatted = _HttpUtils.formatDate(date.toUtc());
- _set("date", formatted);
- }
-
- Date get expires {
- List<String> values = _headers["expires"];
- if (values != null) {
- try {
- return _HttpUtils.parseDate(values[0]);
- } on Exception catch (e) {
- return null;
- }
- }
- return null;
- }
-
- void set expires(Date expires) {
- _checkMutable();
- // Format "Expires" header with date in Greenwich Mean Time (GMT).
- String formatted = _HttpUtils.formatDate(expires.toUtc());
- _set("expires", formatted);
- }
-
- ContentType get contentType {
- var values = _headers["content-type"];
- if (values != null) {
- return new ContentType.fromString(values[0]);
- } else {
- return new ContentType();
- }
- }
-
- void set contentType(ContentType contentType) {
- _checkMutable();
- _set("content-type", contentType.toString());
- }
-
- void _add(String name, Object value) {
- var lowerCaseName = name.toLowerCase();
- // TODO(sgjesse): Add immutable state throw HttpException is immutable.
- if (lowerCaseName == "date") {
- if (value is Date) {
- date = value;
- } else if (value is String) {
- _set("date", value);
- } else {
- throw new HttpException("Unexpected type for header named $name");
- }
- } else if (lowerCaseName == "expires") {
- if (value is Date) {
- expires = value;
- } else if (value is String) {
- _set("expires", value);
- } else {
- throw new HttpException("Unexpected type for header named $name");
- }
- } else if (lowerCaseName == "if-modified-since") {
- if (value is Date) {
- ifModifiedSince = value;
- } else if (value is String) {
- _set("if-modified-since", value);
- } else {
- throw new HttpException("Unexpected type for header named $name");
- }
- } else if (lowerCaseName == "host") {
- int pos = value.indexOf(":");
- if (pos == -1) {
- _host = value;
- _port = HttpClient.DEFAULT_HTTP_PORT;
- } else {
- if (pos > 0) {
- _host = value.substring(0, pos);
- } else {
- _host = null;
- }
- if (pos + 1 == value.length) {
- _port = HttpClient.DEFAULT_HTTP_PORT;
- } else {
- try {
- _port = parseInt(value.substring(pos + 1));
- } on FormatException catch (e) {
- _port = null;
- }
- }
- _set("host", value);
- }
- } else if (lowerCaseName == "content-type") {
- _set("content-type", value);
- } else {
- name = lowerCaseName;
- List<String> values = _headers[name];
- if (values == null) {
- values = new List<String>();
- _headers[name] = values;
- }
- if (value is Date) {
- values.add(_HttpUtils.formatDate(value));
- } else {
- values.add(value.toString());
- }
- }
- }
-
- void _set(String name, String value) {
- name = name.toLowerCase();
- List<String> values = new List<String>();
- _headers[name] = values;
- values.add(value);
- }
-
- _checkMutable() {
- if (!_mutable) throw new HttpException("HTTP headers are not mutable");
- }
-
- _updateHostHeader() {
- bool defaultPort = _port == null || _port == HttpClient.DEFAULT_HTTP_PORT;
- String portPart = defaultPort ? "" : ":$_port";
- _set("host", "$host$portPart");
- }
-
- _foldHeader(String name) {
- if (name == "set-cookie" ||
- (_noFoldingHeaders != null &&
- _noFoldingHeaders.indexOf(name) != -1)) {
- return false;
- }
- return true;
- }
-
- _write(_HttpConnectionBase connection) {
- final COLONSP = const [_CharCode.COLON, _CharCode.SP];
- final COMMASP = const [_CharCode.COMMA, _CharCode.SP];
- final CRLF = const [_CharCode.CR, _CharCode.LF];
-
- var bufferSize = 16 * 1024;
- var buffer = new Uint8List(bufferSize);
- var bufferPos = 0;
-
- void writeBuffer() {
- connection._writeFrom(buffer, 0, bufferPos);
- bufferPos = 0;
- }
-
- // Format headers.
- _headers.forEach((String name, List<String> values) {
- bool fold = _foldHeader(name);
- List<int> nameData;
- nameData = name.charCodes;
- int nameDataLen = nameData.length;
- if (nameDataLen + 2 > bufferSize - bufferPos) writeBuffer();
- buffer.setRange(bufferPos, nameDataLen, nameData);
- bufferPos += nameDataLen;
- buffer[bufferPos++] = _CharCode.COLON;
- buffer[bufferPos++] = _CharCode.SP;
- for (int i = 0; i < values.length; i++) {
- List<int> data = values[i].charCodes;
- int dataLen = data.length;
- // Worst case here is writing the name, value and 6 additional bytes.
- if (nameDataLen + dataLen + 6 > bufferSize - bufferPos) writeBuffer();
- if (i > 0) {
- if (fold) {
- buffer[bufferPos++] = _CharCode.COMMA;
- buffer[bufferPos++] = _CharCode.SP;
- } else {
- buffer[bufferPos++] = _CharCode.CR;
- buffer[bufferPos++] = _CharCode.LF;
- buffer.setRange(bufferPos, nameDataLen, nameData);
- bufferPos += nameDataLen;
- buffer[bufferPos++] = _CharCode.COLON;
- buffer[bufferPos++] = _CharCode.SP;
- }
- }
- buffer.setRange(bufferPos, dataLen, data);
- bufferPos += dataLen;
- }
- buffer[bufferPos++] = _CharCode.CR;
- buffer[bufferPos++] = _CharCode.LF;
- });
- writeBuffer();
- }
-
- String toString() {
- StringBuffer sb = new StringBuffer();
- _headers.forEach((String name, List<String> values) {
- sb.add(name);
- sb.add(": ");
- bool fold = _foldHeader(name);
- for (int i = 0; i < values.length; i++) {
- if (i > 0) {
- if (fold) {
- sb.add(", ");
- } else {
- sb.add("\n");
- sb.add(name);
- sb.add(": ");
- }
- }
- sb.add(values[i]);
- }
- sb.add("\n");
- });
- return sb.toString();
- }
-
- bool _mutable = true; // Are the headers currently mutable?
- Map<String, List<String>> _headers;
- List<String> _noFoldingHeaders;
-
- String _host;
- int _port;
-}
-
-
-class _HeaderValue implements HeaderValue {
- _HeaderValue([String this.value = ""]);
-
- _HeaderValue.fromString(String value, {this.parameterSeparator: ";"}) {
- // Parse the string.
- _parse(value);
- }
-
- Map<String, String> get parameters {
- if (_parameters == null) _parameters = new Map<String, String>();
- return _parameters;
- }
-
- String toString() {
- StringBuffer sb = new StringBuffer();
- sb.add(value);
- if (parameters != null && parameters.length > 0) {
- _parameters.forEach((String name, String value) {
- sb.add("; ");
- sb.add(name);
- sb.add("=");
- sb.add(value);
- });
- }
- return sb.toString();
- }
-
- void _parse(String s) {
- int index = 0;
-
- bool done() => index == s.length;
-
- void skipWS() {
- while (!done()) {
- if (s[index] != " " && s[index] != "\t") return;
- index++;
- }
- }
-
- String parseValue() {
- int start = index;
- while (!done()) {
- if (s[index] == " " ||
- s[index] == "\t" ||
- s[index] == parameterSeparator) break;
- index++;
- }
- return s.substring(start, index).toLowerCase();
- }
-
- void expect(String expected) {
- if (done() || s[index] != expected) {
- throw new HttpException("Failed to parse header value");
- }
- index++;
- }
-
- void maybeExpect(String expected) {
- if (s[index] == expected) index++;
- }
-
- void parseParameters() {
- _parameters = new Map<String, String>();
-
- String parseParameterName() {
- int start = index;
- while (!done()) {
- if (s[index] == " " || s[index] == "\t" || s[index] == "=") break;
- index++;
- }
- return s.substring(start, index).toLowerCase();
- }
-
- String parseParameterValue() {
- if (s[index] == "\"") {
- // Parse quoted value.
- StringBuffer sb = new StringBuffer();
- index++;
- while (!done()) {
- if (s[index] == "\\") {
- if (index + 1 == s.length) {
- throw new HttpException("Failed to parse header value");
- }
- index++;
- } else if (s[index] == "\"") {
- index++;
- break;
- }
- sb.add(s[index]);
- index++;
- }
- return sb.toString();
- } else {
- // Parse non-quoted value.
- return parseValue();
- }
- }
-
- while (!done()) {
- skipWS();
- if (done()) return;
- String name = parseParameterName();
- skipWS();
- expect("=");
- skipWS();
- String value = parseParameterValue();
- _parameters[name] = value;
- skipWS();
- if (done()) return;
- expect(parameterSeparator);
- }
- }
-
- skipWS();
- value = parseValue();
- skipWS();
- if (done()) return;
- maybeExpect(parameterSeparator);
- parseParameters();
- }
-
- String value;
- String parameterSeparator;
- Map<String, String> _parameters;
-}
-
-
-class _ContentType extends _HeaderValue implements ContentType {
- _ContentType(String primaryType, String subType)
- : _primaryType = primaryType, _subType = subType, super("");
-
- _ContentType.fromString(String value) : super.fromString(value);
-
- String get value => "$_primaryType/$_subType";
-
- void set value(String s) {
- int index = s.indexOf("/");
- if (index == -1 || index == (s.length - 1)) {
- primaryType = s.trim().toLowerCase();
- subType = "";
- } else {
- primaryType = s.substring(0, index).trim().toLowerCase();
- subType = s.substring(index + 1).trim().toLowerCase();
- }
- }
-
- String get primaryType => _primaryType;
-
- void set primaryType(String s) {
- _primaryType = s;
- }
-
- String get subType => _subType;
-
- void set subType(String s) {
- _subType = s;
- }
-
- String get charset => parameters["charset"];
-
- void set charset(String s) {
- parameters["charset"] = s;
- }
-
- String _primaryType = "";
- String _subType = "";
-}
-
-
-class _Cookie implements Cookie {
- _Cookie([String this.name, String this.value]);
-
- _Cookie.fromSetCookieValue(String value) {
- // Parse the Set-Cookie header value.
- _parseSetCookieValue(value);
- }
-
- // Parse a Set-Cookie header value according to the rules in RFC 6265.
- void _parseSetCookieValue(String s) {
- int index = 0;
-
- bool done() => index == s.length;
-
- String parseName() {
- int start = index;
- while (!done()) {
- if (s[index] == "=") break;
- index++;
- }
- return s.substring(start, index).trim().toLowerCase();
- }
-
- String parseValue() {
- int start = index;
- while (!done()) {
- if (s[index] == ";") break;
- index++;
- }
- return s.substring(start, index).trim().toLowerCase();
- }
-
- void expect(String expected) {
- if (done()) throw new HttpException("Failed to parse header value [$s]");
- if (s[index] != expected) {
- throw new HttpException("Failed to parse header value [$s]");
- }
- index++;
- }
-
- void parseAttributes() {
- String parseAttributeName() {
- int start = index;
- while (!done()) {
- if (s[index] == "=" || s[index] == ";") break;
- index++;
- }
- return s.substring(start, index).trim().toLowerCase();
- }
-
- String parseAttributeValue() {
- int start = index;
- while (!done()) {
- if (s[index] == ";") break;
- index++;
- }
- return s.substring(start, index).trim().toLowerCase();
- }
-
- while (!done()) {
- String name = parseAttributeName();
- String value = "";
- if (!done() && s[index] == "=") {
- index++; // Skip the = character.
- value = parseAttributeValue();
- }
- if (name == "expires") {
- expires = _HttpUtils.parseCookieDate(value);
- } else if (name == "max-age") {
- maxAge = parseInt(value);
- } else if (name == "domain") {
- domain = value;
- } else if (name == "path") {
- path = value;
- } else if (name == "httponly") {
- httpOnly = true;
- } else if (name == "secure") {
- secure = true;
- }
- if (!done()) index++; // Skip the ; character
- }
- }
-
- name = parseName();
- if (done() || name.length == 0) {
- throw new HttpException("Failed to parse header value [$s]");
- }
- index++; // Skip the = character.
- value = parseValue();
- if (done()) return;
- index++; // Skip the ; character.
- parseAttributes();
- }
-
- String toString() {
- StringBuffer sb = new StringBuffer();
- sb.add(name);
- sb.add("=");
- sb.add(value);
- if (expires != null) {
- sb.add("; Expires=");
- sb.add(_HttpUtils.formatDate(expires));
- }
- if (maxAge != null) {
- sb.add("; Max-Age=");
- sb.add(maxAge);
- }
- if (domain != null) {
- sb.add("; Domain=");
- sb.add(domain);
- }
- if (path != null) {
- sb.add("; Path=");
- sb.add(path);
- }
- if (secure) sb.add("; Secure");
- if (httpOnly) sb.add("; HttpOnly");
- return sb.toString();
- }
-
- String name;
- String value;
- Date expires;
- int maxAge;
- String domain;
- String path;
- bool httpOnly = false;
- bool secure = false;
-}
-
-
// The close queue handles graceful closing of HTTP connections. When
// a connection is added to the queue it will enter a wait state
// waiting for all data written and possibly socket shutdown from
@@ -701,16 +75,13 @@ class _CloseQueue {
class _HttpRequestResponseBase {
- final int START = 0;
- final int HEADER_SENT = 1;
- final int DONE = 2;
- final int UPGRADED = 3;
+ static const int START = 0;
+ static const int HEADER_SENT = 1;
+ static const int DONE = 2;
+ static const int UPGRADED = 3;
_HttpRequestResponseBase(_HttpConnectionBase this._httpConnection)
- : _headers = new _HttpHeaders() {
- _state = START;
- _headResponse = false;
- }
+ : _state = START, _headResponse = false;
int get contentLength => _contentLength;
HttpHeaders get headers => _headers;
@@ -958,17 +329,14 @@ class _HttpRequest extends _HttpRequestResponseBase implements HttpRequest {
return _session = sessionManager.createSession(init);
}
- void _onRequestStart(String method, String uri, String version) {
+ void _onRequestReceived(String method,
+ String uri,
+ String version,
+ _HttpHeaders headers) {
_method = method;
_uri = uri;
_parseRequestUri(uri);
- }
-
- void _onHeaderReceived(String name, String value) {
- _headers.add(name, value);
- }
-
- void _onHeadersComplete() {
+ _headers = headers;
if (_httpConnection._server._sessionManagerInstance != null) {
// Map to session if exists.
var sessionId = cookies.reduce(null, (last, cookie) {
@@ -1055,10 +423,14 @@ class _HttpRequest extends _HttpRequestResponseBase implements HttpRequest {
class _HttpResponse extends _HttpRequestResponseBase implements HttpResponse {
_HttpResponse(_HttpConnection httpConnection)
: super(httpConnection),
- _statusCode = HttpStatus.OK;
+ _statusCode = HttpStatus.OK {
+ _headers = new _HttpHeaders();
+ }
void set contentLength(int contentLength) {
- if (_state >= HEADER_SENT) throw new HttpException("Header already sent");
+ if (_state >= _HttpRequestResponseBase.HEADER_SENT) {
+ throw new HttpException("Header already sent");
+ }
_contentLength = contentLength;
}
@@ -1080,7 +452,9 @@ class _HttpResponse extends _HttpRequestResponseBase implements HttpResponse {
}
OutputStream get outputStream {
- if (_state >= DONE) throw new HttpException("Response closed");
+ if (_state >= _HttpRequestResponseBase.DONE) {
+ throw new HttpException("Response closed");
+ }
if (_outputStream == null) {
_outputStream = new _HttpOutputStream(this);
}
@@ -1088,12 +462,14 @@ class _HttpResponse extends _HttpRequestResponseBase implements HttpResponse {
}
DetachedSocket detachSocket() {
- if (_state >= DONE) throw new HttpException("Response closed");
+ if (_state >= _HttpRequestResponseBase.DONE) {
+ throw new HttpException("Response closed");
+ }
// Ensure that headers are written.
- if (_state == START) {
+ if (_state == _HttpRequestResponseBase.START) {
_writeHeader();
}
- _state = UPGRADED;
+ _state = _HttpRequestResponseBase.UPGRADED;
// Ensure that any trailing data is written.
_writeDone();
// Indicate to the connection that the response handling is done.
@@ -1117,7 +493,7 @@ class _HttpResponse extends _HttpRequestResponseBase implements HttpResponse {
void _streamClose() {
_ensureHeadersSent();
- _state = DONE;
+ _state = _HttpRequestResponseBase.DONE;
// Stop tracking no pending write events.
_httpConnection._onNoPendingWrites = null;
// Ensure that any trailing data is written.
@@ -1127,7 +503,7 @@ class _HttpResponse extends _HttpRequestResponseBase implements HttpResponse {
}
void _streamSetNoPendingWriteHandler(callback()) {
- if (_state != DONE) {
+ if (_state != _HttpRequestResponseBase.DONE) {
_httpConnection._onNoPendingWrites = callback;
}
}
@@ -1246,7 +622,7 @@ class _HttpResponse extends _HttpRequestResponseBase implements HttpResponse {
// Write headers.
bool allWritten = _writeHeaders();
- _state = HEADER_SENT;
+ _state = _HttpRequestResponseBase.HEADER_SENT;
return allWritten;
}
@@ -1444,9 +820,7 @@ class _HttpConnection extends _HttpConnectionBase {
_HttpConnection(HttpServer this._server) {
_httpParser = new _HttpParser.requestParser();
// Register HTTP parser callbacks.
- _httpParser.requestStart = _onRequestStart;
- _httpParser.headerReceived = _onHeaderReceived;
- _httpParser.headersComplete = _onHeadersComplete;
+ _httpParser.requestStart = _onRequestReceived;
_httpParser.dataReceived = _onDataReceived;
_httpParser.dataEnd = _onDataEnd;
_httpParser.error = _onError;
@@ -1472,23 +846,18 @@ class _HttpConnection extends _HttpConnectionBase {
if (_socket != null) _socket.close();
}
- void _onRequestStart(String method, String uri, String version) {
+ void _onRequestReceived(String method,
+ String uri,
+ String version,
+ _HttpHeaders headers) {
_state = _HttpConnectionBase.ACTIVE;
// Create new request and response objects for this request.
_request = new _HttpRequest(this);
_response = new _HttpResponse(this);
- _request._onRequestStart(method, uri, version);
+ _request._onRequestReceived(method, uri, version, headers);
_request._protocolVersion = version;
_response._protocolVersion = version;
_response._headResponse = method == "HEAD";
- }
-
- void _onHeaderReceived(String name, String value) {
- _request._onHeaderReceived(name, value);
- }
-
- void _onHeadersComplete() {
- _request._onHeadersComplete();
_response.persistentConnection = _httpParser.persistentConnection;
if (onRequestReceived != null) {
onRequestReceived(_request, _response);
@@ -1673,6 +1042,7 @@ class _HttpClientRequest
Uri this._uri,
_HttpClientConnection connection)
: super(connection) {
+ _headers = new _HttpHeaders();
_connection = connection;
// Default GET and HEAD requests to have no content.
if (_method == "GET" || _method == "HEAD") {
@@ -1681,7 +1051,9 @@ class _HttpClientRequest
}
void set contentLength(int contentLength) {
- if (_state >= HEADER_SENT) throw new HttpException("Header already sent");
+ if (_state >= _HttpRequestResponseBase.HEADER_SENT) {
+ throw new HttpException("Header already sent");
+ }
_contentLength = contentLength;
}
@@ -1715,7 +1087,7 @@ class _HttpClientRequest
void _streamClose() {
_ensureHeadersSent();
- _state = DONE;
+ _state = _HttpRequestResponseBase.DONE;
// Stop tracking no pending write events.
_httpConnection._onNoPendingWrites = null;
// Ensure that any trailing data is written.
@@ -1724,7 +1096,7 @@ class _HttpClientRequest
}
void _streamSetNoPendingWriteHandler(callback()) {
- if (_state != DONE) {
+ if (_state != _HttpRequestResponseBase.DONE) {
_httpConnection._onNoPendingWrites = callback;
}
}
@@ -1788,7 +1160,7 @@ class _HttpClientRequest
// Write headers.
_writeHeaders();
- _state = HEADER_SENT;
+ _state = _HttpRequestResponseBase.HEADER_SENT;
}
String _method;
@@ -1835,13 +1207,50 @@ class _HttpClientResponse
return _inputStream;
}
- void _onResponseStart(int statusCode, String reasonPhrase, String version) {
+ void _onResponseReceived(int statusCode,
+ String reasonPhrase,
+ String version,
+ _HttpHeaders headers) {
_statusCode = statusCode;
_reasonPhrase = reasonPhrase;
- }
+ _headers = headers;
+ // Get parsed content length.
+ _contentLength = _httpConnection._httpParser.contentLength;
- void _onHeaderReceived(String name, String value) {
- _headers.add(name, value);
+ // Prepare for receiving data.
+ _headers._mutable = false;
+ _buffer = new _BufferList();
+
+ if (isRedirect && _connection.followRedirects) {
+ if (_connection._redirects == null ||
+ _connection._redirects.length < _connection.maxRedirects) {
+ // Check the location header.
+ List<String> location = headers[HttpHeaders.LOCATION];
+ if (location == null || location.length > 1) {
+ throw new RedirectException("Invalid redirect",
+ _connection._redirects);
+ }
+ // Check for redirect loop
+ if (_connection._redirects != null) {
+ Uri redirectUrl = new Uri.fromString(location[0]);
+ for (int i = 0; i < _connection._redirects.length; i++) {
+ if (_connection._redirects[i].location.toString() ==
+ redirectUrl.toString()) {
+ throw new RedirectLoopException(_connection._redirects);
+ }
+ }
+ }
+ // Drain body and redirect.
+ inputStream.onData = inputStream.read;
+ _connection.redirect();
+ } else {
+ throw new RedirectLimitExceededException(_connection._redirects);
+ }
+ } else if (statusCode == HttpStatus.UNAUTHORIZED) {
+ _handleUnauthorized();
+ } else if (_connection._onResponse != null) {
+ _connection._onResponse(this);
+ }
}
void _handleUnauthorized() {
@@ -1917,46 +1326,6 @@ class _HttpClientResponse
}
}
- void _onHeadersComplete() {
- // Get parsed content length.
- _contentLength = _httpConnection._httpParser.contentLength;
-
- // Prepare for receiving data.
- _headers._mutable = false;
- _buffer = new _BufferList();
-
- if (isRedirect && _connection.followRedirects) {
- if (_connection._redirects == null ||
- _connection._redirects.length < _connection.maxRedirects) {
- // Check the location header.
- List<String> location = headers[HttpHeaders.LOCATION];
- if (location == null || location.length > 1) {
- throw new RedirectException("Invalid redirect",
- _connection._redirects);
- }
- // Check for redirect loop
- if (_connection._redirects != null) {
- Uri redirectUrl = new Uri.fromString(location[0]);
- for (int i = 0; i < _connection._redirects.length; i++) {
- if (_connection._redirects[i].location.toString() ==
- redirectUrl.toString()) {
- throw new RedirectLoopException(_connection._redirects);
- }
- }
- }
- // Drain body and redirect.
- inputStream.onData = inputStream.read;
- _connection.redirect();
- } else {
- throw new RedirectLimitExceededException(_connection._redirects);
- }
- } else if (statusCode == HttpStatus.UNAUTHORIZED) {
- _handleUnauthorized();
- } else if (_connection._onResponse != null) {
- _connection._onResponse(this);
- }
- }
-
void _onDataReceived(List<int> data) {
_buffer.add(data);
if (_inputStream != null) _inputStream._dataReceived();
@@ -2011,9 +1380,7 @@ class _HttpClientConnection
super._connectionEstablished(socketConn._socket);
_socketConn = socketConn;
// Register HTTP parser callbacks.
- _httpParser.responseStart = _onResponseStart;
- _httpParser.headerReceived = _onHeaderReceived;
- _httpParser.headersComplete = _onHeadersComplete;
+ _httpParser.responseStart = _onResponseReceived;
_httpParser.dataReceived = _onDataReceived;
_httpParser.dataEnd = _onDataEnd;
_httpParser.error = _onError;
@@ -2086,16 +1453,11 @@ class _HttpClientConnection
}
}
- void _onResponseStart(int statusCode, String reasonPhrase, String version) {
- _response._onResponseStart(statusCode, reasonPhrase, version);
- }
-
- void _onHeaderReceived(String name, String value) {
- _response._onHeaderReceived(name, value);
- }
-
- void _onHeadersComplete() {
- _response._onHeadersComplete();
+ void _onResponseReceived(int statusCode,
+ String reasonPhrase,
+ String version,
+ _HttpHeaders headers) {
+ _response._onResponseReceived(statusCode, reasonPhrase, version, headers);
}
void _onDataReceived(List<int> data) {
« no previous file with comments | « no previous file | sdk/lib/io/http_parser.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698