Index: sdk/lib/io/http_impl.dart |
diff --git a/sdk/lib/io/http_impl.dart b/sdk/lib/io/http_impl.dart |
index 889a32e04638d807b9a9b46d9ae0e67390f5200f..bc681a3a4b7d9719fc2e707e915101c77e354ba9 100644 |
--- a/sdk/lib/io/http_impl.dart |
+++ b/sdk/lib/io/http_impl.dart |
@@ -38,18 +38,12 @@ class _HttpIncoming extends Stream<List<int>> { |
_HttpIncoming(this.headers, this._transferLength, this._stream); |
StreamSubscription<List<int>> listen(void onData(List<int> event), |
- {Function onError, |
- void onDone(), |
- bool cancelOnError}) { |
+ {Function onError, void onDone(), bool cancelOnError}) { |
hasSubscriber = true; |
- return _stream |
- .handleError((error) { |
- throw new HttpException(error.message, uri: uri); |
- }) |
- .listen(onData, |
- onError: onError, |
- onDone: onDone, |
- cancelOnError: cancelOnError); |
+ return _stream.handleError((error) { |
+ throw new HttpException(error.message, uri: uri); |
+ }).listen(onData, |
+ onError: onError, onDone: onDone, cancelOnError: cancelOnError); |
} |
// Is completed once all data have been received. |
@@ -79,7 +73,6 @@ abstract class _HttpInboundMessage extends Stream<List<int>> { |
bool get persistentConnection => headers.persistentConnection; |
} |
- |
class _HttpRequest extends _HttpInboundMessage implements HttpRequest { |
final HttpResponse response; |
@@ -92,11 +85,12 @@ class _HttpRequest extends _HttpInboundMessage implements HttpRequest { |
Uri _requestedUri; |
_HttpRequest(this.response, _HttpIncoming _incoming, this._httpServer, |
- this._httpConnection) : super(_incoming) { |
+ this._httpConnection) |
+ : super(_incoming) { |
if (headers.protocolVersion == "1.1") { |
response.headers |
- ..chunkedTransferEncoding = true |
- ..persistentConnection = headers.persistentConnection; |
+ ..chunkedTransferEncoding = true |
+ ..persistentConnection = headers.persistentConnection; |
} |
if (_httpServer._sessionManagerInstance != null) { |
@@ -115,13 +109,9 @@ class _HttpRequest extends _HttpInboundMessage implements HttpRequest { |
} |
StreamSubscription<List<int>> listen(void onData(List<int> event), |
- {Function onError, |
- void onDone(), |
- bool cancelOnError}) { |
+ {Function onError, void onDone(), bool cancelOnError}) { |
return _incoming.listen(onData, |
- onError: onError, |
- onDone: onDone, |
- cancelOnError: cancelOnError); |
+ onError: onError, onDone: onDone, cancelOnError: cancelOnError); |
} |
Uri get uri => _incoming.uri; |
@@ -129,8 +119,9 @@ class _HttpRequest extends _HttpInboundMessage implements HttpRequest { |
Uri get requestedUri { |
if (_requestedUri == null) { |
var proto = headers['x-forwarded-proto']; |
- var scheme = proto != null ? proto.first : |
- _httpConnection._socket is SecureSocket ? "https" : "http"; |
+ var scheme = proto != null |
+ ? proto.first |
+ : _httpConnection._socket is SecureSocket ? "https" : "http"; |
var hostList = headers['x-forwarded-host']; |
String host; |
if (hostList != null) { |
@@ -174,9 +165,8 @@ class _HttpRequest extends _HttpInboundMessage implements HttpRequest { |
} |
} |
- |
-class _HttpClientResponse |
- extends _HttpInboundMessage implements HttpClientResponse { |
+class _HttpClientResponse extends _HttpInboundMessage |
+ implements HttpClientResponse { |
List<RedirectInfo> get redirects => _httpRequest._responseRedirects; |
// The HttpClient this response belongs to. |
@@ -185,8 +175,9 @@ class _HttpClientResponse |
// The HttpClientRequest of this response. |
final _HttpClientRequest _httpRequest; |
- _HttpClientResponse(_HttpIncoming _incoming, this._httpRequest, |
- this._httpClient) : super(_incoming) { |
+ _HttpClientResponse( |
+ _HttpIncoming _incoming, this._httpRequest, this._httpClient) |
+ : super(_incoming) { |
// Set uri for potential exceptions. |
_incoming.uri = _httpRequest.uri; |
} |
@@ -215,18 +206,17 @@ class _HttpClientResponse |
bool get isRedirect { |
if (_httpRequest.method == "GET" || _httpRequest.method == "HEAD") { |
return statusCode == HttpStatus.MOVED_PERMANENTLY || |
- statusCode == HttpStatus.FOUND || |
- statusCode == HttpStatus.SEE_OTHER || |
- statusCode == HttpStatus.TEMPORARY_REDIRECT; |
+ statusCode == HttpStatus.FOUND || |
+ statusCode == HttpStatus.SEE_OTHER || |
+ statusCode == HttpStatus.TEMPORARY_REDIRECT; |
} else if (_httpRequest.method == "POST") { |
return statusCode == HttpStatus.SEE_OTHER; |
} |
return false; |
} |
- Future<HttpClientResponse> redirect([String method, |
- Uri url, |
- bool followLoops]) { |
+ Future<HttpClientResponse> redirect( |
+ [String method, Uri url, bool followLoops]) { |
if (method == null) { |
// Set method as defined by RFC 2616 section 10.3.4. |
if (statusCode == HttpStatus.SEE_OTHER && _httpRequest.method == "POST") { |
@@ -250,19 +240,18 @@ class _HttpClientResponse |
} |
} |
} |
- return _httpClient._openUrlFromRequest(method, url, _httpRequest) |
+ return _httpClient |
+ ._openUrlFromRequest(method, url, _httpRequest) |
.then((request) { |
- request._responseRedirects |
- ..addAll(this.redirects) |
- ..add(new _RedirectInfo(statusCode, method, url)); |
- return request.close(); |
- }); |
+ request._responseRedirects |
+ ..addAll(this.redirects) |
+ ..add(new _RedirectInfo(statusCode, method, url)); |
+ return request.close(); |
+ }); |
} |
StreamSubscription<List<int>> listen(void onData(List<int> event), |
- {Function onError, |
- void onDone(), |
- bool cancelOnError}) { |
+ {Function onError, void onDone(), bool cancelOnError}) { |
if (_incoming.upgraded) { |
// If upgraded, the connection is already 'removed' form the client. |
// Since listening to upgraded data is 'bogus', simply close and |
@@ -276,9 +265,7 @@ class _HttpClientResponse |
stream = stream.transform(GZIP.decoder); |
} |
return stream.listen(onData, |
- onError: onError, |
- onDone: onDone, |
- cancelOnError: cancelOnError); |
+ onError: onError, onDone: onDone, cancelOnError: cancelOnError); |
} |
Future<Socket> detachSocket() { |
@@ -292,36 +279,39 @@ class _HttpClientResponse |
// Only try to authenticate if there is a challenge in the response. |
List<String> challenge = headers[HttpHeaders.PROXY_AUTHENTICATE]; |
return statusCode == HttpStatus.PROXY_AUTHENTICATION_REQUIRED && |
- challenge != null && challenge.length == 1; |
+ challenge != null && |
+ challenge.length == 1; |
} |
bool get _shouldAuthenticate { |
// Only try to authenticate if there is a challenge in the response. |
List<String> challenge = headers[HttpHeaders.WWW_AUTHENTICATE]; |
return statusCode == HttpStatus.UNAUTHORIZED && |
- challenge != null && challenge.length == 1; |
+ challenge != null && |
+ challenge.length == 1; |
} |
Future<HttpClientResponse> _authenticate(bool proxyAuth) { |
Future<HttpClientResponse> retry() { |
// Drain body and retry. |
return drain().then((_) { |
- return _httpClient._openUrlFromRequest(_httpRequest.method, |
- _httpRequest.uri, |
- _httpRequest) |
- .then((request) => request.close()); |
- }); |
+ return _httpClient |
+ ._openUrlFromRequest( |
+ _httpRequest.method, _httpRequest.uri, _httpRequest) |
+ .then((request) => request.close()); |
+ }); |
} |
List<String> authChallenge() { |
- return proxyAuth ? headers[HttpHeaders.PROXY_AUTHENTICATE] |
- : headers[HttpHeaders.WWW_AUTHENTICATE]; |
+ return proxyAuth |
+ ? headers[HttpHeaders.PROXY_AUTHENTICATE] |
+ : headers[HttpHeaders.WWW_AUTHENTICATE]; |
} |
_Credentials findCredentials(_AuthenticationScheme scheme) { |
- return proxyAuth ? _httpClient._findProxyCredentials(_httpRequest._proxy, |
- scheme) |
- : _httpClient._findCredentials(_httpRequest.uri, scheme); |
+ return proxyAuth |
+ ? _httpClient._findProxyCredentials(_httpRequest._proxy, scheme) |
+ : _httpClient._findCredentials(_httpRequest.uri, scheme); |
} |
void removeCredentials(_Credentials cr) { |
@@ -338,17 +328,14 @@ class _HttpClientResponse |
return new Future.value(false); |
} |
var proxy = _httpRequest._proxy; |
- return _httpClient._authenticateProxy(proxy.host, |
- proxy.port, |
- scheme.toString(), |
- realm); |
+ return _httpClient._authenticateProxy( |
+ proxy.host, proxy.port, scheme.toString(), realm); |
} else { |
if (_httpClient._authenticate == null) { |
return new Future.value(false); |
} |
- return _httpClient._authenticate(_httpRequest.uri, |
- scheme.toString(), |
- realm); |
+ return _httpClient._authenticate( |
+ _httpRequest.uri, scheme.toString(), realm); |
} |
} |
@@ -374,12 +361,13 @@ class _HttpClientResponse |
// Digest authentication only supports the MD5 algorithm. |
if (cr.scheme == _AuthenticationScheme.DIGEST && |
(header.parameters["algorithm"] == null || |
- header.parameters["algorithm"].toLowerCase() == "md5")) { |
+ header.parameters["algorithm"].toLowerCase() == "md5")) { |
if (cr.nonce == null || cr.nonce == header.parameters["nonce"]) { |
// If the nonce is not set then this is the first authenticate |
// response for these credentials. Set up authentication state. |
if (cr.nonce == null) { |
- cr..nonce = header.parameters["nonce"] |
+ cr |
+ ..nonce = header.parameters["nonce"] |
..algorithm = "MD5" |
..qop = header.parameters["qop"] |
..nonceCount = 0; |
@@ -387,7 +375,7 @@ class _HttpClientResponse |
// Credentials where found, prepare for retrying the request. |
return retry(); |
} else if (header.parameters["stale"] != null && |
- header.parameters["stale"].toLowerCase() == "true") { |
+ header.parameters["stale"].toLowerCase() == "true") { |
// If stale is true retry with new nonce. |
cr.nonce = header.parameters["nonce"]; |
// Credentials where found, prepare for retrying the request. |
@@ -415,7 +403,6 @@ class _HttpClientResponse |
} |
} |
- |
abstract class _HttpOutboundMessage<T> extends _IOSinkImpl { |
// Used to mark when the body should be written. This is used for HEAD |
// requests and in error handling. |
@@ -428,16 +415,13 @@ abstract class _HttpOutboundMessage<T> extends _IOSinkImpl { |
final _HttpHeaders headers; |
- _HttpOutboundMessage(Uri uri, |
- String protocolVersion, |
- _HttpOutgoing outgoing, |
- {_HttpHeaders initialHeaders}) |
+ _HttpOutboundMessage(Uri uri, String protocolVersion, _HttpOutgoing outgoing, |
+ {_HttpHeaders initialHeaders}) |
: _uri = uri, |
- headers = new _HttpHeaders( |
- protocolVersion, |
- defaultPortForScheme: uri.scheme == 'https' ? |
- HttpClient.DEFAULT_HTTPS_PORT : |
- HttpClient.DEFAULT_HTTP_PORT, |
+ headers = new _HttpHeaders(protocolVersion, |
+ defaultPortForScheme: uri.scheme == 'https' |
+ ? HttpClient.DEFAULT_HTTPS_PORT |
+ : HttpClient.DEFAULT_HTTP_PORT, |
initialHeaders: initialHeaders), |
_outgoing = outgoing, |
super(outgoing, null) { |
@@ -461,7 +445,6 @@ abstract class _HttpOutboundMessage<T> extends _IOSinkImpl { |
_bufferOutput = bufferOutput; |
} |
- |
Encoding get encoding { |
if (_encodingSet && _outgoing.headersWritten) { |
return _encoding; |
@@ -493,7 +476,6 @@ abstract class _HttpOutboundMessage<T> extends _IOSinkImpl { |
bool get _isConnectionClosed => false; |
} |
- |
class _HttpResponse extends _HttpOutboundMessage<HttpResponse> |
implements HttpResponse { |
int _statusCode = 200; |
@@ -503,11 +485,8 @@ class _HttpResponse extends _HttpOutboundMessage<HttpResponse> |
Duration _deadline; |
Timer _deadlineTimer; |
- _HttpResponse(Uri uri, |
- String protocolVersion, |
- _HttpOutgoing outgoing, |
- HttpHeaders defaultHeaders, |
- String serverHeader) |
+ _HttpResponse(Uri uri, String protocolVersion, _HttpOutgoing outgoing, |
+ HttpHeaders defaultHeaders, String serverHeader) |
: super(uri, protocolVersion, outgoing, initialHeaders: defaultHeaders) { |
if (serverHeader != null) headers.set('server', serverHeader); |
} |
@@ -540,11 +519,11 @@ class _HttpResponse extends _HttpOutboundMessage<HttpResponse> |
Future<Socket> detachSocket({bool writeHeaders: true}) { |
if (_outgoing.headersWritten) throw new StateError("Headers already sent"); |
- deadline = null; // Be sure to stop any deadline. |
+ deadline = null; // Be sure to stop any deadline. |
var future = _httpRequest._httpConnection.detachSocket(); |
if (writeHeaders) { |
- var headersFuture = _outgoing.writeHeaders(drainRequest: false, |
- setOutgoing: false); |
+ var headersFuture = |
+ _outgoing.writeHeaders(drainRequest: false, setOutgoing: false); |
assert(headersFuture == null); |
} else { |
// Imitate having written the headers. |
@@ -598,17 +577,17 @@ class _HttpResponse extends _HttpOutboundMessage<HttpResponse> |
for (int i = 0; i < cookies.length; i++) { |
if (cookies[i].name.toUpperCase() == _DART_SESSION_ID) { |
cookies[i] |
- ..value = session.id |
- ..httpOnly = true |
- ..path = "/"; |
+ ..value = session.id |
+ ..httpOnly = true |
+ ..path = "/"; |
found = true; |
} |
} |
if (!found) { |
var cookie = new Cookie(_DART_SESSION_ID, session.id); |
cookies.add(cookie |
- ..httpOnly = true |
- ..path = "/"); |
+ ..httpOnly = true |
+ ..path = "/"); |
} |
} |
// Add all the cookies set to the headers. |
@@ -634,57 +613,92 @@ class _HttpResponse extends _HttpOutboundMessage<HttpResponse> |
} |
switch (statusCode) { |
- case HttpStatus.CONTINUE: return "Continue"; |
- case HttpStatus.SWITCHING_PROTOCOLS: return "Switching Protocols"; |
- case HttpStatus.OK: return "OK"; |
- case HttpStatus.CREATED: return "Created"; |
- case HttpStatus.ACCEPTED: return "Accepted"; |
+ case HttpStatus.CONTINUE: |
+ return "Continue"; |
+ case HttpStatus.SWITCHING_PROTOCOLS: |
+ return "Switching Protocols"; |
+ case HttpStatus.OK: |
+ return "OK"; |
+ case HttpStatus.CREATED: |
+ return "Created"; |
+ case HttpStatus.ACCEPTED: |
+ return "Accepted"; |
case HttpStatus.NON_AUTHORITATIVE_INFORMATION: |
return "Non-Authoritative Information"; |
- case HttpStatus.NO_CONTENT: return "No Content"; |
- case HttpStatus.RESET_CONTENT: return "Reset Content"; |
- case HttpStatus.PARTIAL_CONTENT: return "Partial Content"; |
- case HttpStatus.MULTIPLE_CHOICES: return "Multiple Choices"; |
- case HttpStatus.MOVED_PERMANENTLY: return "Moved Permanently"; |
- case HttpStatus.FOUND: return "Found"; |
- case HttpStatus.SEE_OTHER: return "See Other"; |
- case HttpStatus.NOT_MODIFIED: return "Not Modified"; |
- case HttpStatus.USE_PROXY: return "Use Proxy"; |
- case HttpStatus.TEMPORARY_REDIRECT: return "Temporary Redirect"; |
- case HttpStatus.BAD_REQUEST: return "Bad Request"; |
- case HttpStatus.UNAUTHORIZED: return "Unauthorized"; |
- case HttpStatus.PAYMENT_REQUIRED: return "Payment Required"; |
- case HttpStatus.FORBIDDEN: return "Forbidden"; |
- case HttpStatus.NOT_FOUND: return "Not Found"; |
- case HttpStatus.METHOD_NOT_ALLOWED: return "Method Not Allowed"; |
- case HttpStatus.NOT_ACCEPTABLE: return "Not Acceptable"; |
+ case HttpStatus.NO_CONTENT: |
+ return "No Content"; |
+ case HttpStatus.RESET_CONTENT: |
+ return "Reset Content"; |
+ case HttpStatus.PARTIAL_CONTENT: |
+ return "Partial Content"; |
+ case HttpStatus.MULTIPLE_CHOICES: |
+ return "Multiple Choices"; |
+ case HttpStatus.MOVED_PERMANENTLY: |
+ return "Moved Permanently"; |
+ case HttpStatus.FOUND: |
+ return "Found"; |
+ case HttpStatus.SEE_OTHER: |
+ return "See Other"; |
+ case HttpStatus.NOT_MODIFIED: |
+ return "Not Modified"; |
+ case HttpStatus.USE_PROXY: |
+ return "Use Proxy"; |
+ case HttpStatus.TEMPORARY_REDIRECT: |
+ return "Temporary Redirect"; |
+ case HttpStatus.BAD_REQUEST: |
+ return "Bad Request"; |
+ case HttpStatus.UNAUTHORIZED: |
+ return "Unauthorized"; |
+ case HttpStatus.PAYMENT_REQUIRED: |
+ return "Payment Required"; |
+ case HttpStatus.FORBIDDEN: |
+ return "Forbidden"; |
+ case HttpStatus.NOT_FOUND: |
+ return "Not Found"; |
+ case HttpStatus.METHOD_NOT_ALLOWED: |
+ return "Method Not Allowed"; |
+ case HttpStatus.NOT_ACCEPTABLE: |
+ return "Not Acceptable"; |
case HttpStatus.PROXY_AUTHENTICATION_REQUIRED: |
return "Proxy Authentication Required"; |
- case HttpStatus.REQUEST_TIMEOUT: return "Request Time-out"; |
- case HttpStatus.CONFLICT: return "Conflict"; |
- case HttpStatus.GONE: return "Gone"; |
- case HttpStatus.LENGTH_REQUIRED: return "Length Required"; |
- case HttpStatus.PRECONDITION_FAILED: return "Precondition Failed"; |
+ case HttpStatus.REQUEST_TIMEOUT: |
+ return "Request Time-out"; |
+ case HttpStatus.CONFLICT: |
+ return "Conflict"; |
+ case HttpStatus.GONE: |
+ return "Gone"; |
+ case HttpStatus.LENGTH_REQUIRED: |
+ return "Length Required"; |
+ case HttpStatus.PRECONDITION_FAILED: |
+ return "Precondition Failed"; |
case HttpStatus.REQUEST_ENTITY_TOO_LARGE: |
return "Request Entity Too Large"; |
- case HttpStatus.REQUEST_URI_TOO_LONG: return "Request-URI Too Large"; |
- case HttpStatus.UNSUPPORTED_MEDIA_TYPE: return "Unsupported Media Type"; |
+ case HttpStatus.REQUEST_URI_TOO_LONG: |
+ return "Request-URI Too Large"; |
+ case HttpStatus.UNSUPPORTED_MEDIA_TYPE: |
+ return "Unsupported Media Type"; |
case HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE: |
return "Requested range not satisfiable"; |
- case HttpStatus.EXPECTATION_FAILED: return "Expectation Failed"; |
- case HttpStatus.INTERNAL_SERVER_ERROR: return "Internal Server Error"; |
- case HttpStatus.NOT_IMPLEMENTED: return "Not Implemented"; |
- case HttpStatus.BAD_GATEWAY: return "Bad Gateway"; |
- case HttpStatus.SERVICE_UNAVAILABLE: return "Service Unavailable"; |
- case HttpStatus.GATEWAY_TIMEOUT: return "Gateway Time-out"; |
+ case HttpStatus.EXPECTATION_FAILED: |
+ return "Expectation Failed"; |
+ case HttpStatus.INTERNAL_SERVER_ERROR: |
+ return "Internal Server Error"; |
+ case HttpStatus.NOT_IMPLEMENTED: |
+ return "Not Implemented"; |
+ case HttpStatus.BAD_GATEWAY: |
+ return "Bad Gateway"; |
+ case HttpStatus.SERVICE_UNAVAILABLE: |
+ return "Service Unavailable"; |
+ case HttpStatus.GATEWAY_TIMEOUT: |
+ return "Gateway Time-out"; |
case HttpStatus.HTTP_VERSION_NOT_SUPPORTED: |
return "Http Version not supported"; |
- default: return "Status $statusCode"; |
+ default: |
+ return "Status $statusCode"; |
} |
} |
} |
- |
class _HttpClientRequest extends _HttpOutboundMessage<HttpClientResponse> |
implements HttpClientRequest { |
final String method; |
@@ -695,8 +709,8 @@ class _HttpClientRequest extends _HttpOutboundMessage<HttpClientResponse> |
final _HttpClient _httpClient; |
final _HttpClientConnection _httpClientConnection; |
- final Completer<HttpClientResponse> _responseCompleter |
- = new Completer<HttpClientResponse>(); |
+ final Completer<HttpClientResponse> _responseCompleter = |
+ new Completer<HttpClientResponse>(); |
final _Proxy _proxy; |
@@ -710,7 +724,7 @@ class _HttpClientRequest extends _HttpOutboundMessage<HttpClientResponse> |
List<RedirectInfo> _responseRedirects = []; |
_HttpClientRequest(_HttpOutgoing outgoing, Uri uri, this.method, this._proxy, |
- this._httpClient, this._httpClientConnection) |
+ this._httpClient, this._httpClientConnection) |
: uri = uri, |
super(uri, "1.1", outgoing) { |
// GET and HEAD have 'content-length: 0' by default. |
@@ -724,8 +738,7 @@ class _HttpClientRequest extends _HttpOutboundMessage<HttpClientResponse> |
Future<HttpClientResponse> get done { |
if (_response == null) { |
_response = Future.wait([_responseCompleter.future, super.done], |
- eagerError: true) |
- .then((list) => list[0]); |
+ eagerError: true).then((list) => list[0]); |
} |
return _response; |
} |
@@ -755,15 +768,14 @@ class _HttpClientRequest extends _HttpOutboundMessage<HttpClientResponse> |
if (followRedirects && response.isRedirect) { |
if (response.redirects.length < maxRedirects) { |
// Redirect and drain response. |
- future = response.drain() |
+ future = response |
+ .drain() |
.then<HttpClientResponse>((_) => response.redirect()); |
} else { |
// End with exception, too many redirects. |
- future = response.drain() |
- .then<HttpClientResponse>((_) { |
- return new Future<HttpClientResponse>.error( |
- new RedirectException("Redirect limit exceeded", |
- response.redirects)); |
+ future = response.drain().then<HttpClientResponse>((_) { |
+ return new Future<HttpClientResponse>.error(new RedirectException( |
+ "Redirect limit exceeded", response.redirects)); |
}); |
} |
} else if (response._shouldAuthenticateProxy) { |
@@ -773,8 +785,7 @@ class _HttpClientRequest extends _HttpOutboundMessage<HttpClientResponse> |
} else { |
future = new Future<HttpClientResponse>.value(response); |
} |
- future.then( |
- (v) => _responseCompleter.complete(v), |
+ future.then((v) => _responseCompleter.complete(v), |
onError: _responseCompleter.completeError); |
} |
@@ -868,7 +879,6 @@ class _HttpGZipSink extends ByteConversionSink { |
void close() {} |
} |
- |
// The _HttpOutgoing handles all of the following: |
// - Buffering |
// - GZip compressionm |
@@ -878,12 +888,23 @@ class _HttpGZipSink extends ByteConversionSink { |
// Most notable is the GZip compression, that uses a double-buffering system, |
// one before gzip (_gzipBuffer) and one after (_buffer). |
class _HttpOutgoing implements StreamConsumer<List<int>> { |
- static const List<int> _footerAndChunk0Length = |
- const [_CharCode.CR, _CharCode.LF, 0x30, _CharCode.CR, _CharCode.LF, |
- _CharCode.CR, _CharCode.LF]; |
- |
- static const List<int> _chunk0Length = |
- const [0x30, _CharCode.CR, _CharCode.LF, _CharCode.CR, _CharCode.LF]; |
+ static const List<int> _footerAndChunk0Length = const [ |
+ _CharCode.CR, |
+ _CharCode.LF, |
+ 0x30, |
+ _CharCode.CR, |
+ _CharCode.LF, |
+ _CharCode.CR, |
+ _CharCode.LF |
+ ]; |
+ |
+ static const List<int> _chunk0Length = const [ |
+ 0x30, |
+ _CharCode.CR, |
+ _CharCode.LF, |
+ _CharCode.CR, |
+ _CharCode.LF |
+ ]; |
final Completer<Socket> _doneCompleter = new Completer<Socket>(); |
final Socket socket; |
@@ -965,7 +986,6 @@ class _HttpOutgoing implements StreamConsumer<List<int>> { |
return null; |
} |
- |
Future addStream(Stream<List<int>> stream) { |
if (_socketError) { |
stream.listen(null).cancel(); |
@@ -984,9 +1004,7 @@ class _HttpOutgoing implements StreamConsumer<List<int>> { |
// alternative is to use stream.extand, but that won't give us a way of |
// pausing. |
var controller = new StreamController<List<int>>( |
- onPause: () => sub.pause(), |
- onResume: () => sub.resume(), |
- sync: true); |
+ onPause: () => sub.pause(), onResume: () => sub.resume(), sync: true); |
void onData(List<int> data) { |
if (_socketError) return; |
@@ -1016,8 +1034,7 @@ class _HttpOutgoing implements StreamConsumer<List<int>> { |
_addChunk(data, controller.add); |
} |
- sub = stream.listen( |
- onData, |
+ sub = stream.listen(onData, |
onError: controller.addError, |
onDone: controller.close, |
cancelOnError: true); |
@@ -1030,20 +1047,19 @@ class _HttpOutgoing implements StreamConsumer<List<int>> { |
sub.pause(future); |
} |
} |
- return socket.addStream(controller.stream) |
- .then((_) { |
- return outbound; |
- }, onError: (error, stackTrace) { |
- // Be sure to close it in case of an error. |
- if (_gzip) _gzipSink.close(); |
- _socketError = true; |
- _doneCompleter.completeError(error, stackTrace); |
- if (_ignoreError(error)) { |
- return outbound; |
- } else { |
- throw error; |
- } |
- }); |
+ return socket.addStream(controller.stream).then((_) { |
+ return outbound; |
+ }, onError: (error, stackTrace) { |
+ // Be sure to close it in case of an error. |
+ if (_gzip) _gzipSink.close(); |
+ _socketError = true; |
+ _doneCompleter.completeError(error, stackTrace); |
+ if (_ignoreError(error)) { |
+ return outbound; |
+ } else { |
+ throw error; |
+ } |
+ }); |
} |
Future close() { |
@@ -1062,9 +1078,9 @@ class _HttpOutgoing implements StreamConsumer<List<int>> { |
outbound.headers.contentLength = 0; |
} else if (outbound.headers.contentLength > 0) { |
var error = new HttpException( |
- "No content even though contentLength was specified to be " |
- "greater than 0: ${outbound.headers.contentLength}.", |
- uri: outbound._uri); |
+ "No content even though contentLength was specified to be " |
+ "greater than 0: ${outbound.headers.contentLength}.", |
+ uri: outbound._uri); |
_doneCompleter.completeError(error); |
return _closeFuture = new Future.error(error); |
} |
@@ -1089,8 +1105,8 @@ class _HttpOutgoing implements StreamConsumer<List<int>> { |
if (_gzip) { |
_gzipAdd = socket.add; |
if (_gzipBufferLength > 0) { |
- _gzipSink.add(new Uint8List.view( |
- _gzipBuffer.buffer, 0, _gzipBufferLength)); |
+ _gzipSink.add( |
+ new Uint8List.view(_gzipBuffer.buffer, 0, _gzipBufferLength)); |
} |
_gzipBuffer = null; |
_gzipSink.close(); |
@@ -1107,18 +1123,17 @@ class _HttpOutgoing implements StreamConsumer<List<int>> { |
// And finally flush it. As we support keep-alive, never close it from |
// here. Once the socket is flushed, we'll be able to reuse it (signaled |
// by the 'done' future). |
- return socket.flush() |
- .then((_) { |
- _doneCompleter.complete(socket); |
+ return socket.flush().then((_) { |
+ _doneCompleter.complete(socket); |
+ return outbound; |
+ }, onError: (error, stackTrace) { |
+ _doneCompleter.completeError(error, stackTrace); |
+ if (_ignoreError(error)) { |
return outbound; |
- }, onError: (error, stackTrace) { |
- _doneCompleter.completeError(error, stackTrace); |
- if (_ignoreError(error)) { |
- return outbound; |
- } else { |
- throw error; |
- } |
- }); |
+ } else { |
+ throw error; |
+ } |
+ }); |
} |
var future = writeHeaders(); |
@@ -1142,20 +1157,19 @@ class _HttpOutgoing implements StreamConsumer<List<int>> { |
_gzipBuffer = new Uint8List(_OUTGOING_BUFFER_SIZE); |
assert(_gzipSink == null); |
_gzipSink = new ZLibEncoder(gzip: true) |
- .startChunkedConversion( |
- new _HttpGZipSink((data) { |
- // We are closing down prematurely, due to an error. Discard. |
- if (_gzipAdd == null) return; |
- _addChunk(_chunkHeader(data.length), _gzipAdd); |
- _pendingChunkedFooter = 2; |
- _addChunk(data, _gzipAdd); |
- })); |
+ .startChunkedConversion(new _HttpGZipSink((data) { |
+ // We are closing down prematurely, due to an error. Discard. |
+ if (_gzipAdd == null) return; |
+ _addChunk(_chunkHeader(data.length), _gzipAdd); |
+ _pendingChunkedFooter = 2; |
+ _addChunk(data, _gzipAdd); |
+ })); |
} |
} |
- bool _ignoreError(error) |
- => (error is SocketException || error is TlsException) && |
- outbound is HttpResponse; |
+ bool _ignoreError(error) => |
+ (error is SocketException || error is TlsException) && |
+ outbound is HttpResponse; |
void _addGZipChunk(List<int> chunk, void add(List<int> data)) { |
if (!outbound.bufferOutput) { |
@@ -1163,17 +1177,15 @@ class _HttpOutgoing implements StreamConsumer<List<int>> { |
return; |
} |
if (chunk.length > _gzipBuffer.length - _gzipBufferLength) { |
- add(new Uint8List.view( |
- _gzipBuffer.buffer, 0, _gzipBufferLength)); |
+ add(new Uint8List.view(_gzipBuffer.buffer, 0, _gzipBufferLength)); |
_gzipBuffer = new Uint8List(_OUTGOING_BUFFER_SIZE); |
_gzipBufferLength = 0; |
} |
if (chunk.length > _OUTGOING_BUFFER_SIZE) { |
add(chunk); |
} else { |
- _gzipBuffer.setRange(_gzipBufferLength, |
- _gzipBufferLength + chunk.length, |
- chunk); |
+ _gzipBuffer.setRange( |
+ _gzipBufferLength, _gzipBufferLength + chunk.length, chunk); |
_gzipBufferLength += chunk.length; |
} |
} |
@@ -1204,8 +1216,24 @@ class _HttpOutgoing implements StreamConsumer<List<int>> { |
} |
List<int> _chunkHeader(int length) { |
- const hexDigits = const [0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, |
- 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46]; |
+ const hexDigits = const [ |
+ 0x30, |
+ 0x31, |
+ 0x32, |
+ 0x33, |
+ 0x34, |
+ 0x35, |
+ 0x36, |
+ 0x37, |
+ 0x38, |
+ 0x39, |
+ 0x41, |
+ 0x42, |
+ 0x43, |
+ 0x44, |
+ 0x45, |
+ 0x46 |
+ ]; |
if (length == 0) { |
if (_pendingChunkedFooter == 2) return _footerAndChunk0Length; |
return _chunk0Length; |
@@ -1250,94 +1278,85 @@ class _HttpClientConnection { |
Future<Socket> _streamFuture; |
_HttpClientConnection(this.key, this._socket, this._httpClient, |
- [this._proxyTunnel = false, this._context]) |
+ [this._proxyTunnel = false, this._context]) |
: _httpParser = new _HttpParser.responseParser() { |
_httpParser.listenToStream(_socket); |
// Set up handlers on the parser here, so we are sure to get 'onDone' from |
// the parser. |
- _subscription = _httpParser.listen( |
- (incoming) { |
- // Only handle one incoming response at the time. Keep the |
- // stream paused until the response have been processed. |
- _subscription.pause(); |
- // We assume the response is not here, until we have send the request. |
- if (_nextResponseCompleter == null) { |
- throw new HttpException( |
- "Unexpected response (unsolicited response without request).", |
- uri: _currentUri); |
- } |
+ _subscription = _httpParser.listen((incoming) { |
+ // Only handle one incoming response at the time. Keep the |
+ // stream paused until the response have been processed. |
+ _subscription.pause(); |
+ // We assume the response is not here, until we have send the request. |
+ if (_nextResponseCompleter == null) { |
+ throw new HttpException( |
+ "Unexpected response (unsolicited response without request).", |
+ uri: _currentUri); |
+ } |
- // Check for status code '100 Continue'. In that case just |
- // consume that response as the final response will follow |
- // it. There is currently no API for the client to wait for |
- // the '100 Continue' response. |
- if (incoming.statusCode == 100) { |
- incoming.drain().then((_) { |
- _subscription.resume(); |
- }).catchError((error, [StackTrace stackTrace]) { |
- _nextResponseCompleter.completeError( |
- new HttpException(error.message, uri: _currentUri), |
- stackTrace); |
- _nextResponseCompleter = null; |
- }); |
- } else { |
- _nextResponseCompleter.complete(incoming); |
- _nextResponseCompleter = null; |
- } |
- }, |
- onError: (error, [StackTrace stackTrace]) { |
- if (_nextResponseCompleter != null) { |
- _nextResponseCompleter.completeError( |
- new HttpException(error.message, uri: _currentUri), |
- stackTrace); |
- _nextResponseCompleter = null; |
- } |
- }, |
- onDone: () { |
- if (_nextResponseCompleter != null) { |
- _nextResponseCompleter.completeError(new HttpException( |
- "Connection closed before response was received", |
- uri: _currentUri)); |
- _nextResponseCompleter = null; |
- } |
- close(); |
+ // Check for status code '100 Continue'. In that case just |
+ // consume that response as the final response will follow |
+ // it. There is currently no API for the client to wait for |
+ // the '100 Continue' response. |
+ if (incoming.statusCode == 100) { |
+ incoming.drain().then((_) { |
+ _subscription.resume(); |
+ }).catchError((error, [StackTrace stackTrace]) { |
+ _nextResponseCompleter.completeError( |
+ new HttpException(error.message, uri: _currentUri), stackTrace); |
+ _nextResponseCompleter = null; |
}); |
+ } else { |
+ _nextResponseCompleter.complete(incoming); |
+ _nextResponseCompleter = null; |
+ } |
+ }, onError: (error, [StackTrace stackTrace]) { |
+ if (_nextResponseCompleter != null) { |
+ _nextResponseCompleter.completeError( |
+ new HttpException(error.message, uri: _currentUri), stackTrace); |
+ _nextResponseCompleter = null; |
+ } |
+ }, onDone: () { |
+ if (_nextResponseCompleter != null) { |
+ _nextResponseCompleter.completeError(new HttpException( |
+ "Connection closed before response was received", |
+ uri: _currentUri)); |
+ _nextResponseCompleter = null; |
+ } |
+ close(); |
+ }); |
} |
_HttpClientRequest send(Uri uri, int port, String method, _Proxy proxy) { |
if (closed) { |
- throw new HttpException( |
- "Socket closed before request was sent", uri: uri); |
+ throw new HttpException("Socket closed before request was sent", |
+ uri: uri); |
} |
_currentUri = uri; |
// Start with pausing the parser. |
_subscription.pause(); |
- _ProxyCredentials proxyCreds; // Credentials used to authorize proxy. |
- _SiteCredentials creds; // Credentials used to authorize this request. |
+ _ProxyCredentials proxyCreds; // Credentials used to authorize proxy. |
+ _SiteCredentials creds; // Credentials used to authorize this request. |
var outgoing = new _HttpOutgoing(_socket); |
// Create new request object, wrapping the outgoing connection. |
- var request = new _HttpClientRequest(outgoing, |
- uri, |
- method, |
- proxy, |
- _httpClient, |
- this); |
+ var request = |
+ new _HttpClientRequest(outgoing, uri, method, proxy, _httpClient, this); |
// For the Host header an IPv6 address must be enclosed in []'s. |
var host = uri.host; |
if (host.contains(':')) host = "[$host]"; |
request.headers |
- ..host = host |
- ..port = port |
- .._add(HttpHeaders.ACCEPT_ENCODING, "gzip"); |
+ ..host = host |
+ ..port = port |
+ .._add(HttpHeaders.ACCEPT_ENCODING, "gzip"); |
if (_httpClient.userAgent != null) { |
request.headers._add('user-agent', _httpClient.userAgent); |
} |
if (proxy.isAuthenticated) { |
// If the proxy configuration contains user information use that |
// for proxy basic authorization. |
- String auth = _CryptoUtils.bytesToBase64( |
- UTF8.encode("${proxy.username}:${proxy.password}")); |
+ String auth = _CryptoUtils |
+ .bytesToBase64(UTF8.encode("${proxy.username}:${proxy.password}")); |
request.headers.set(HttpHeaders.PROXY_AUTHORIZATION, "Basic $auth"); |
} else if (!proxy.isDirect && _httpClient._proxyCredentials.length > 0) { |
proxyCreds = _httpClient._findProxyCredentials(proxy); |
@@ -1348,8 +1367,7 @@ class _HttpClientConnection { |
if (uri.userInfo != null && !uri.userInfo.isEmpty) { |
// If the URL contains user information use that for basic |
// authorization. |
- String auth = |
- _CryptoUtils.bytesToBase64(UTF8.encode(uri.userInfo)); |
+ String auth = _CryptoUtils.bytesToBase64(UTF8.encode(uri.userInfo)); |
request.headers.set(HttpHeaders.AUTHORIZATION, "Basic $auth"); |
} else { |
// Look for credentials. |
@@ -1361,80 +1379,74 @@ class _HttpClientConnection { |
// Start sending the request (lazy, delayed until the user provides |
// data). |
_httpParser.isHead = method == "HEAD"; |
- _streamFuture = outgoing.done |
- .then<Socket>((Socket s) { |
- // Request sent, set up response completer. |
- _nextResponseCompleter = new Completer(); |
- |
- // Listen for response. |
- _nextResponseCompleter.future |
- .then((incoming) { |
- _currentUri = null; |
- incoming.dataDone.then((closing) { |
- if (incoming.upgraded) { |
- _httpClient._connectionClosed(this); |
- startTimer(); |
- return; |
- } |
- if (closed) return; |
- if (!closing && |
- !_dispose && |
- incoming.headers.persistentConnection && |
- request.persistentConnection) { |
- // Return connection, now we are done. |
- _httpClient._returnConnection(this); |
- _subscription.resume(); |
- } else { |
- destroy(); |
- } |
- }); |
- // For digest authentication if proxy check if the proxy |
- // requests the client to start using a new nonce for proxy |
- // authentication. |
- if (proxyCreds != null && |
- proxyCreds.scheme == _AuthenticationScheme.DIGEST) { |
- var authInfo = incoming.headers["proxy-authentication-info"]; |
- if (authInfo != null && authInfo.length == 1) { |
- var header = |
- _HeaderValue.parse( |
- authInfo[0], parameterSeparator: ','); |
- var nextnonce = header.parameters["nextnonce"]; |
- if (nextnonce != null) proxyCreds.nonce = nextnonce; |
- } |
- } |
- // For digest authentication check if the server requests the |
- // client to start using a new nonce. |
- if (creds != null && |
- creds.scheme == _AuthenticationScheme.DIGEST) { |
- var authInfo = incoming.headers["authentication-info"]; |
- if (authInfo != null && authInfo.length == 1) { |
- var header = |
- _HeaderValue.parse( |
- authInfo[0], parameterSeparator: ','); |
- var nextnonce = header.parameters["nextnonce"]; |
- if (nextnonce != null) creds.nonce = nextnonce; |
- } |
- } |
- request._onIncoming(incoming); |
- }) |
- // If we see a state error, we failed to get the 'first' |
- // element. |
- .catchError((error) { |
- throw new HttpException( |
- "Connection closed before data was received", uri: uri); |
- }, test: (error) => error is StateError) |
- .catchError((error, stackTrace) { |
- // We are done with the socket. |
- destroy(); |
- request._onError(error, stackTrace); |
- }); |
- |
- // Resume the parser now we have a handler. |
- _subscription.resume(); |
- return s; |
- }, onError: (e) { |
- destroy(); |
+ _streamFuture = outgoing.done.then<Socket>((Socket s) { |
+ // Request sent, set up response completer. |
+ _nextResponseCompleter = new Completer(); |
+ |
+ // Listen for response. |
+ _nextResponseCompleter.future.then((incoming) { |
+ _currentUri = null; |
+ incoming.dataDone.then((closing) { |
+ if (incoming.upgraded) { |
+ _httpClient._connectionClosed(this); |
+ startTimer(); |
+ return; |
+ } |
+ if (closed) return; |
+ if (!closing && |
+ !_dispose && |
+ incoming.headers.persistentConnection && |
+ request.persistentConnection) { |
+ // Return connection, now we are done. |
+ _httpClient._returnConnection(this); |
+ _subscription.resume(); |
+ } else { |
+ destroy(); |
+ } |
}); |
+ // For digest authentication if proxy check if the proxy |
+ // requests the client to start using a new nonce for proxy |
+ // authentication. |
+ if (proxyCreds != null && |
+ proxyCreds.scheme == _AuthenticationScheme.DIGEST) { |
+ var authInfo = incoming.headers["proxy-authentication-info"]; |
+ if (authInfo != null && authInfo.length == 1) { |
+ var header = |
+ _HeaderValue.parse(authInfo[0], parameterSeparator: ','); |
+ var nextnonce = header.parameters["nextnonce"]; |
+ if (nextnonce != null) proxyCreds.nonce = nextnonce; |
+ } |
+ } |
+ // For digest authentication check if the server requests the |
+ // client to start using a new nonce. |
+ if (creds != null && creds.scheme == _AuthenticationScheme.DIGEST) { |
+ var authInfo = incoming.headers["authentication-info"]; |
+ if (authInfo != null && authInfo.length == 1) { |
+ var header = |
+ _HeaderValue.parse(authInfo[0], parameterSeparator: ','); |
+ var nextnonce = header.parameters["nextnonce"]; |
+ if (nextnonce != null) creds.nonce = nextnonce; |
+ } |
+ } |
+ request._onIncoming(incoming); |
+ }) |
+ // If we see a state error, we failed to get the 'first' |
+ // element. |
+ .catchError((error) { |
+ throw new HttpException("Connection closed before data was received", |
+ uri: uri); |
+ }, test: (error) => error is StateError).catchError((error, stackTrace) { |
+ // We are done with the socket. |
+ destroy(); |
+ request._onError(error, stackTrace); |
+ }); |
+ |
+ // Resume the parser now we have a handler. |
+ _subscription.resume(); |
+ return s; |
+ }, onError: (e) { |
+ destroy(); |
+ }); |
return request; |
} |
@@ -1453,43 +1465,37 @@ class _HttpClientConnection { |
closed = true; |
_httpClient._connectionClosed(this); |
_streamFuture |
- // TODO(ajohnsen): Add timeout. |
+ // TODO(ajohnsen): Add timeout. |
.then((_) => _socket.destroy()); |
} |
Future<_HttpClientConnection> createProxyTunnel(String host, int port, |
_Proxy proxy, bool callback(X509Certificate certificate)) { |
_HttpClientRequest request = |
- send(new Uri(host: host, port: port), |
- port, |
- "CONNECT", |
- proxy); |
+ send(new Uri(host: host, port: port), port, "CONNECT", proxy); |
if (proxy.isAuthenticated) { |
// If the proxy configuration contains user information use that |
// for proxy basic authorization. |
- String auth = _CryptoUtils.bytesToBase64( |
- UTF8.encode("${proxy.username}:${proxy.password}")); |
+ String auth = _CryptoUtils |
+ .bytesToBase64(UTF8.encode("${proxy.username}:${proxy.password}")); |
request.headers.set(HttpHeaders.PROXY_AUTHORIZATION, "Basic $auth"); |
} |
- return request.close() |
- .then((response) { |
- if (response.statusCode != HttpStatus.OK) { |
- throw "Proxy failed to establish tunnel " |
- "(${response.statusCode} ${response.reasonPhrase})"; |
- } |
- var socket = (response as _HttpClientResponse)._httpRequest |
- ._httpClientConnection._socket; |
- return SecureSocket.secure( |
- socket, |
- host: host, |
- context: _context, |
- onBadCertificate: callback); |
- }) |
- .then((secureSocket) { |
- String key = _HttpClientConnection.makeKey(true, host, port); |
- return new _HttpClientConnection( |
- key, secureSocket, request._httpClient, true); |
- }); |
+ return request.close().then((response) { |
+ if (response.statusCode != HttpStatus.OK) { |
+ throw "Proxy failed to establish tunnel " |
+ "(${response.statusCode} ${response.reasonPhrase})"; |
+ } |
+ var socket = (response as _HttpClientResponse) |
+ ._httpRequest |
+ ._httpClientConnection |
+ ._socket; |
+ return SecureSocket.secure(socket, |
+ host: host, context: _context, onBadCertificate: callback); |
+ }).then((secureSocket) { |
+ String key = _HttpClientConnection.makeKey(true, host, port); |
+ return new _HttpClientConnection( |
+ key, secureSocket, request._httpClient, true); |
+ }); |
} |
HttpConnectionInfo get connectionInfo => _HttpConnectionInfo.create(_socket); |
@@ -1507,12 +1513,10 @@ class _HttpClientConnection { |
void startTimer() { |
assert(_idleTimer == null); |
- _idleTimer = new Timer( |
- _httpClient.idleTimeout, |
- () { |
- _idleTimer = null; |
- close(); |
- }); |
+ _idleTimer = new Timer(_httpClient.idleTimeout, () { |
+ _idleTimer = null; |
+ close(); |
+ }); |
} |
} |
@@ -1523,7 +1527,6 @@ class _ConnectionInfo { |
_ConnectionInfo(this.connection, this.proxy); |
} |
- |
class _ConnectionTarget { |
// Unique key for this connection target. |
final String key; |
@@ -1536,11 +1539,8 @@ class _ConnectionTarget { |
final Queue _pending = new ListQueue(); |
int _connecting = 0; |
- _ConnectionTarget(this.key, |
- this.host, |
- this.port, |
- this.isSecure, |
- this.context); |
+ _ConnectionTarget( |
+ this.key, this.host, this.port, this.isSecure, this.context); |
bool get isEmpty => _idle.isEmpty && _active.isEmpty && _connecting == 0; |
@@ -1593,10 +1593,8 @@ class _ConnectionTarget { |
} |
} |
- Future<_ConnectionInfo> connect(String uriHost, |
- int uriPort, |
- _Proxy proxy, |
- _HttpClient client) { |
+ Future<_ConnectionInfo> connect( |
+ String uriHost, int uriPort, _Proxy proxy, _HttpClient client) { |
if (hasIdle) { |
var connection = takeIdle(); |
client._connectionsChanged(); |
@@ -1618,34 +1616,34 @@ class _ConnectionTarget { |
} |
Future socketFuture = (isSecure && proxy.isDirect |
- ? SecureSocket.connect(host, |
- port, |
- context: context, |
- onBadCertificate: callback) |
+ ? SecureSocket.connect(host, port, |
+ context: context, onBadCertificate: callback) |
: Socket.connect(host, port)); |
_connecting++; |
return socketFuture.then((socket) { |
- _connecting--; |
- socket.setOption(SocketOption.TCP_NODELAY, true); |
- var connection = |
- new _HttpClientConnection(key, socket, client, false, context); |
- if (isSecure && !proxy.isDirect) { |
- connection._dispose = true; |
- return connection.createProxyTunnel(uriHost, uriPort, proxy, callback) |
- .then((tunnel) { |
- client._getConnectionTarget(uriHost, uriPort, true) |
- .addNewActive(tunnel); |
- return new _ConnectionInfo(tunnel, proxy); |
- }); |
- } else { |
- addNewActive(connection); |
- return new _ConnectionInfo(connection, proxy); |
- } |
- }, onError: (error) { |
- _connecting--; |
- _checkPending(); |
- throw error; |
- }); |
+ _connecting--; |
+ socket.setOption(SocketOption.TCP_NODELAY, true); |
+ var connection = |
+ new _HttpClientConnection(key, socket, client, false, context); |
+ if (isSecure && !proxy.isDirect) { |
+ connection._dispose = true; |
+ return connection |
+ .createProxyTunnel(uriHost, uriPort, proxy, callback) |
+ .then((tunnel) { |
+ client |
+ ._getConnectionTarget(uriHost, uriPort, true) |
+ .addNewActive(tunnel); |
+ return new _ConnectionInfo(tunnel, proxy); |
+ }); |
+ } else { |
+ addNewActive(connection); |
+ return new _ConnectionInfo(connection, proxy); |
+ } |
+ }, onError: (error) { |
+ _connecting--; |
+ _checkPending(); |
+ throw error; |
+ }); |
} |
} |
@@ -1654,8 +1652,8 @@ typedef bool BadCertificateCallback(X509Certificate cr, String host, int port); |
class _HttpClient implements HttpClient { |
bool _closing = false; |
bool _closingForcefully = false; |
- final Map<String, _ConnectionTarget> _connectionTargets |
- = new HashMap<String, _ConnectionTarget>(); |
+ final Map<String, _ConnectionTarget> _connectionTargets = |
+ new HashMap<String, _ConnectionTarget>(); |
final List<_Credentials> _credentials = []; |
final List<_ProxyCredentials> _proxyCredentials = []; |
final SecurityContext _context; |
@@ -1686,17 +1684,13 @@ class _HttpClient implements HttpClient { |
} |
} |
- set badCertificateCallback(bool callback(X509Certificate cert, |
- String host, |
- int port)) { |
+ set badCertificateCallback( |
+ bool callback(X509Certificate cert, String host, int port)) { |
_badCertificateCallback = callback; |
} |
- |
- Future<HttpClientRequest> open(String method, |
- String host, |
- int port, |
- String path) { |
+ Future<HttpClientRequest> open( |
+ String method, String host, int port, String path) { |
const int hashMark = 0x23; |
const int questionMark = 0x3f; |
int fragmentStart = path.length; |
@@ -1715,41 +1709,41 @@ class _HttpClient implements HttpClient { |
query = path.substring(queryStart + 1, fragmentStart); |
path = path.substring(0, queryStart); |
} |
- Uri uri = new Uri(scheme: "http", host: host, port: port, |
- path: path, query: query); |
+ Uri uri = new Uri( |
+ scheme: "http", host: host, port: port, path: path, query: query); |
return _openUrl(method, uri); |
} |
- Future<HttpClientRequest> openUrl(String method, Uri url) |
- => _openUrl(method, url); |
+ Future<HttpClientRequest> openUrl(String method, Uri url) => |
+ _openUrl(method, url); |
- Future<HttpClientRequest> get(String host, int port, String path) |
- => open("get", host, port, path); |
+ Future<HttpClientRequest> get(String host, int port, String path) => |
+ open("get", host, port, path); |
Future<HttpClientRequest> getUrl(Uri url) => _openUrl("get", url); |
- Future<HttpClientRequest> post(String host, int port, String path) |
- => open("post", host, port, path); |
+ Future<HttpClientRequest> post(String host, int port, String path) => |
+ open("post", host, port, path); |
Future<HttpClientRequest> postUrl(Uri url) => _openUrl("post", url); |
- Future<HttpClientRequest> put(String host, int port, String path) |
- => open("put", host, port, path); |
+ Future<HttpClientRequest> put(String host, int port, String path) => |
+ open("put", host, port, path); |
Future<HttpClientRequest> putUrl(Uri url) => _openUrl("put", url); |
- Future<HttpClientRequest> delete(String host, int port, String path) |
- => open("delete", host, port, path); |
+ Future<HttpClientRequest> delete(String host, int port, String path) => |
+ open("delete", host, port, path); |
Future<HttpClientRequest> deleteUrl(Uri url) => _openUrl("delete", url); |
- Future<HttpClientRequest> head(String host, int port, String path) |
- => open("head", host, port, path); |
+ Future<HttpClientRequest> head(String host, int port, String path) => |
+ open("head", host, port, path); |
Future<HttpClientRequest> headUrl(Uri url) => _openUrl("head", url); |
- Future<HttpClientRequest> patch(String host, int port, String path) |
- => open("patch", host, port, path); |
+ Future<HttpClientRequest> patch(String host, int port, String path) => |
+ open("patch", host, port, path); |
Future<HttpClientRequest> patchUrl(Uri url) => _openUrl("patch", url); |
@@ -1758,8 +1752,8 @@ class _HttpClient implements HttpClient { |
_closingForcefully = force; |
_closeConnections(_closingForcefully); |
assert(!_connectionTargets.values.any((s) => s.hasIdle)); |
- assert(!force || |
- !_connectionTargets.values.any((s) => s._active.isNotEmpty)); |
+ assert( |
+ !force || !_connectionTargets.values.any((s) => s._active.isNotEmpty)); |
} |
set authenticate(Future<bool> f(Uri url, String scheme, String realm)) { |
@@ -1775,10 +1769,8 @@ class _HttpClient implements HttpClient { |
_authenticateProxy = f; |
} |
- void addProxyCredentials(String host, |
- int port, |
- String realm, |
- HttpClientCredentials cr) { |
+ void addProxyCredentials( |
+ String host, int port, String realm, HttpClientCredentials cr) { |
_proxyCredentials.add(new _ProxyCredentials(host, port, realm, cr)); |
} |
@@ -1803,9 +1795,9 @@ class _HttpClient implements HttpClient { |
bool isSecure = (uri.scheme == "https"); |
int port = uri.port; |
if (port == 0) { |
- port = isSecure ? |
- HttpClient.DEFAULT_HTTPS_PORT : |
- HttpClient.DEFAULT_HTTP_PORT; |
+ port = isSecure |
+ ? HttpClient.DEFAULT_HTTPS_PORT |
+ : HttpClient.DEFAULT_HTTP_PORT; |
} |
// Check to see if a proxy server should be used for this connection. |
var proxyConf = const _ProxyConfiguration.direct(); |
@@ -1820,47 +1812,41 @@ class _HttpClient implements HttpClient { |
} |
return _getConnection(uri.host, port, proxyConf, isSecure) |
.then((_ConnectionInfo info) { |
+ _HttpClientRequest send(_ConnectionInfo info) { |
+ return info.connection |
+ .send(uri, port, method.toUpperCase(), info.proxy); |
+ } |
- _HttpClientRequest send(_ConnectionInfo info) { |
- return info.connection.send(uri, |
- port, |
- method.toUpperCase(), |
- info.proxy); |
- } |
- |
- // If the connection was closed before the request was sent, create |
- // and use another connection. |
- if (info.connection.closed) { |
- return _getConnection(uri.host, port, proxyConf, isSecure) |
- .then(send); |
- } |
- return send(info); |
- }); |
+ // If the connection was closed before the request was sent, create |
+ // and use another connection. |
+ if (info.connection.closed) { |
+ return _getConnection(uri.host, port, proxyConf, isSecure).then(send); |
+ } |
+ return send(info); |
+ }); |
} |
- Future<_HttpClientRequest> _openUrlFromRequest(String method, |
- Uri uri, |
- _HttpClientRequest previous) { |
+ Future<_HttpClientRequest> _openUrlFromRequest( |
+ String method, Uri uri, _HttpClientRequest previous) { |
// If the new URI is relative (to either '/' or some sub-path), |
// construct a full URI from the previous one. |
Uri resolved = previous.uri.resolveUri(uri); |
return _openUrl(method, resolved).then((_HttpClientRequest request) { |
- |
- request |
- // Only follow redirects if initial request did. |
- ..followRedirects = previous.followRedirects |
- // Allow same number of redirects. |
- ..maxRedirects = previous.maxRedirects; |
- // Copy headers. |
- for (var header in previous.headers._headers.keys) { |
- if (request.headers[header] == null) { |
- request.headers.set(header, previous.headers[header]); |
- } |
- } |
- return request |
- ..headers.chunkedTransferEncoding = false |
- ..contentLength = 0; |
- }); |
+ request |
+ // Only follow redirects if initial request did. |
+ ..followRedirects = previous.followRedirects |
+ // Allow same number of redirects. |
+ ..maxRedirects = previous.maxRedirects; |
+ // Copy headers. |
+ for (var header in previous.headers._headers.keys) { |
+ if (request.headers[header] == null) { |
+ request.headers.set(header, previous.headers[header]); |
+ } |
+ } |
+ return request |
+ ..headers.chunkedTransferEncoding = false |
+ ..contentLength = 0; |
+ }); |
} |
// Return a live connection to the idle pool. |
@@ -1902,22 +1888,21 @@ class _HttpClient implements HttpClient { |
} |
// Get a new _HttpClientConnection, from the matching _ConnectionTarget. |
- Future<_ConnectionInfo> _getConnection(String uriHost, |
- int uriPort, |
- _ProxyConfiguration proxyConf, |
- bool isSecure) { |
+ Future<_ConnectionInfo> _getConnection(String uriHost, int uriPort, |
+ _ProxyConfiguration proxyConf, bool isSecure) { |
Iterator<_Proxy> proxies = proxyConf.proxies.iterator; |
Future<_ConnectionInfo> connect(error) { |
if (!proxies.moveNext()) return new Future.error(error); |
_Proxy proxy = proxies.current; |
- String host = proxy.isDirect ? uriHost: proxy.host; |
- int port = proxy.isDirect ? uriPort: proxy.port; |
+ String host = proxy.isDirect ? uriHost : proxy.host; |
+ int port = proxy.isDirect ? uriPort : proxy.port; |
return _getConnectionTarget(host, port, isSecure) |
.connect(uriHost, uriPort, proxy, this) |
// On error, continue with next proxy. |
.catchError(connect); |
} |
+ |
// Make sure we go through the event loop before taking a |
// connection from the pool. For long-running synchronous code the |
// server might have closed the connection, so this lowers the |
@@ -1930,21 +1915,21 @@ class _HttpClient implements HttpClient { |
// Look for credentials. |
_SiteCredentials cr = |
_credentials.fold(null, (_SiteCredentials prev, value) { |
- var siteCredentials = value as _SiteCredentials; |
- if (siteCredentials.applies(url, scheme)) { |
- if (prev == null) return value; |
- return siteCredentials.uri.path.length > prev.uri.path.length |
- ? siteCredentials |
- : prev; |
- } else { |
- return prev; |
- } |
- }); |
+ var siteCredentials = value as _SiteCredentials; |
+ if (siteCredentials.applies(url, scheme)) { |
+ if (prev == null) return value; |
+ return siteCredentials.uri.path.length > prev.uri.path.length |
+ ? siteCredentials |
+ : prev; |
+ } else { |
+ return prev; |
+ } |
+ }); |
return cr; |
} |
_ProxyCredentials _findProxyCredentials(_Proxy proxy, |
- [_AuthenticationScheme scheme]) { |
+ [_AuthenticationScheme scheme]) { |
// Look for credentials. |
var it = _proxyCredentials.iterator; |
while (it.moveNext()) { |
@@ -1969,18 +1954,17 @@ class _HttpClient implements HttpClient { |
} |
} |
- static String _findProxyFromEnvironment(Uri url, |
- Map<String, String> environment) { |
+ static String _findProxyFromEnvironment( |
+ Uri url, Map<String, String> environment) { |
checkNoProxy(String option) { |
if (option == null) return null; |
Iterator<String> names = option.split(",").map((s) => s.trim()).iterator; |
while (names.moveNext()) { |
var name = names.current; |
if ((name.startsWith("[") && |
- name.endsWith("]") && |
- "[${url.host}]" == name) || |
- (name.isNotEmpty && |
- url.host.endsWith(name))) { |
+ name.endsWith("]") && |
+ "[${url.host}]" == name) || |
+ (name.isNotEmpty && url.host.endsWith(name))) { |
return "DIRECT"; |
} |
} |
@@ -2039,9 +2023,8 @@ class _HttpClient implements HttpClient { |
static Map<String, String> _platformEnvironmentCache = Platform.environment; |
} |
- |
-class _HttpConnection |
- extends LinkedListEntry<_HttpConnection> with _ServiceObject { |
+class _HttpConnection extends LinkedListEntry<_HttpConnection> |
+ with _ServiceObject { |
static const _ACTIVE = 0; |
static const _IDLE = 1; |
static const _CLOSING = 2; |
@@ -2061,61 +2044,62 @@ class _HttpConnection |
_HttpConnection(this._socket, this._httpServer) |
: _httpParser = new _HttpParser.requestParser() { |
- try { _socket._owner = this; } catch (_) { print(_); } |
+ try { |
+ _socket._owner = this; |
+ } catch (_) { |
+ print(_); |
+ } |
_connections[_serviceId] = this; |
_httpParser.listenToStream(_socket as Object/*=Socket*/); |
- _subscription = _httpParser.listen( |
- (incoming) { |
- _httpServer._markActive(this); |
- // If the incoming was closed, close the connection. |
- incoming.dataDone.then((closing) { |
- if (closing) destroy(); |
- }); |
- // Only handle one incoming request at the time. Keep the |
- // stream paused until the request has been send. |
- _subscription.pause(); |
- _state = _ACTIVE; |
- var outgoing = new _HttpOutgoing(_socket); |
- var response = new _HttpResponse(incoming.uri, |
- incoming.headers.protocolVersion, |
- outgoing, |
- _httpServer.defaultResponseHeaders, |
- _httpServer.serverHeader); |
- var request = new _HttpRequest(response, incoming, _httpServer, this); |
- _streamFuture = outgoing.done |
- .then((_) { |
- response.deadline = null; |
- if (_state == _DETACHED) return; |
- if (response.persistentConnection && |
- request.persistentConnection && |
- incoming.fullBodyRead && |
- !_httpParser.upgrade && |
- !_httpServer.closed) { |
- _state = _IDLE; |
- _idleMark = false; |
- _httpServer._markIdle(this); |
- // Resume the subscription for incoming requests as the |
- // request is now processed. |
- _subscription.resume(); |
- } else { |
- // Close socket, keep-alive not used or body sent before |
- // received data was handled. |
- destroy(); |
- } |
- }, onError: (_) { |
- destroy(); |
- }); |
- outgoing.ignoreBody = request.method == "HEAD"; |
- response._httpRequest = request; |
- _httpServer._handleRequest(request); |
- }, |
- onDone: () { |
- destroy(); |
- }, |
- onError: (error) { |
- // Ignore failed requests that was closed before headers was received. |
+ _subscription = _httpParser.listen((incoming) { |
+ _httpServer._markActive(this); |
+ // If the incoming was closed, close the connection. |
+ incoming.dataDone.then((closing) { |
+ if (closing) destroy(); |
+ }); |
+ // Only handle one incoming request at the time. Keep the |
+ // stream paused until the request has been send. |
+ _subscription.pause(); |
+ _state = _ACTIVE; |
+ var outgoing = new _HttpOutgoing(_socket); |
+ var response = new _HttpResponse( |
+ incoming.uri, |
+ incoming.headers.protocolVersion, |
+ outgoing, |
+ _httpServer.defaultResponseHeaders, |
+ _httpServer.serverHeader); |
+ var request = new _HttpRequest(response, incoming, _httpServer, this); |
+ _streamFuture = outgoing.done.then((_) { |
+ response.deadline = null; |
+ if (_state == _DETACHED) return; |
+ if (response.persistentConnection && |
+ request.persistentConnection && |
+ incoming.fullBodyRead && |
+ !_httpParser.upgrade && |
+ !_httpServer.closed) { |
+ _state = _IDLE; |
+ _idleMark = false; |
+ _httpServer._markIdle(this); |
+ // Resume the subscription for incoming requests as the |
+ // request is now processed. |
+ _subscription.resume(); |
+ } else { |
+ // Close socket, keep-alive not used or body sent before |
+ // received data was handled. |
destroy(); |
- }); |
+ } |
+ }, onError: (_) { |
+ destroy(); |
+ }); |
+ outgoing.ignoreBody = request.method == "HEAD"; |
+ response._httpRequest = request; |
+ _httpServer._handleRequest(request); |
+ }, onDone: () { |
+ destroy(); |
+ }, onError: (error) { |
+ // Ignore failed requests that was closed before headers was received. |
+ destroy(); |
+ }); |
} |
void markIdle() { |
@@ -2179,20 +2163,29 @@ class _HttpConnection |
}; |
} |
switch (_state) { |
- case _ACTIVE: r['state'] = "Active"; break; |
- case _IDLE: r['state'] = "Idle"; break; |
- case _CLOSING: r['state'] = "Closing"; break; |
- case _DETACHED: r['state'] = "Detached"; break; |
- default: r['state'] = 'Unknown'; break; |
+ case _ACTIVE: |
+ r['state'] = "Active"; |
+ break; |
+ case _IDLE: |
+ r['state'] = "Idle"; |
+ break; |
+ case _CLOSING: |
+ r['state'] = "Closing"; |
+ break; |
+ case _DETACHED: |
+ r['state'] = "Detached"; |
+ break; |
+ default: |
+ r['state'] = 'Unknown'; |
+ break; |
} |
return r; |
} |
} |
- |
// HTTP server waiting for socket connections. |
-class _HttpServer |
- extends Stream<HttpRequest> with _ServiceObject |
+class _HttpServer extends Stream<HttpRequest> |
+ with _ServiceObject |
implements HttpServer { |
// Use default Map so we keep order. |
static Map<int, _HttpServer> _servers = new Map<int, _HttpServer>(); |
@@ -2206,47 +2199,48 @@ class _HttpServer |
static Future<HttpServer> bind( |
address, int port, int backlog, bool v6Only, bool shared) { |
- return ServerSocket.bind( |
- address, port, backlog: backlog, v6Only: v6Only, shared: shared) |
- .then((socket) { |
- return new _HttpServer._(socket, true); |
- }); |
- } |
- |
- static Future<HttpServer> bindSecure(address, |
- int port, |
- SecurityContext context, |
- int backlog, |
- bool v6Only, |
- bool requestClientCertificate, |
- bool shared) { |
- return SecureServerSocket.bind( |
- address, |
- port, |
- context, |
- backlog: backlog, |
- v6Only: v6Only, |
- requestClientCertificate: requestClientCertificate, |
- shared: shared) |
- .then((socket) { |
- return new _HttpServer._(socket, true); |
- }); |
+ return ServerSocket |
+ .bind(address, port, backlog: backlog, v6Only: v6Only, shared: shared) |
+ .then((socket) { |
+ return new _HttpServer._(socket, true); |
+ }); |
+ } |
+ |
+ static Future<HttpServer> bindSecure( |
+ address, |
+ int port, |
+ SecurityContext context, |
+ int backlog, |
+ bool v6Only, |
+ bool requestClientCertificate, |
+ bool shared) { |
+ return SecureServerSocket |
+ .bind(address, port, context, |
+ backlog: backlog, |
+ v6Only: v6Only, |
+ requestClientCertificate: requestClientCertificate, |
+ shared: shared) |
+ .then((socket) { |
+ return new _HttpServer._(socket, true); |
+ }); |
} |
_HttpServer._(this._serverSocket, this._closeServer) { |
- _controller = new StreamController<HttpRequest>(sync: true, |
- onCancel: close); |
+ _controller = |
+ new StreamController<HttpRequest>(sync: true, onCancel: close); |
idleTimeout = const Duration(seconds: 120); |
_servers[_serviceId] = this; |
_serverSocket._owner = this; |
} |
_HttpServer.listenOn(this._serverSocket) : _closeServer = false { |
- _controller = new StreamController<HttpRequest>(sync: true, |
- onCancel: close); |
+ _controller = |
+ new StreamController<HttpRequest>(sync: true, onCancel: close); |
idleTimeout = const Duration(seconds: 120); |
_servers[_serviceId] = this; |
- try { _serverSocket._owner = this; } catch (_) {} |
+ try { |
+ _serverSocket._owner = this; |
+ } catch (_) {} |
} |
static HttpHeaders _initDefaultResponseHeaders() { |
@@ -2280,28 +2274,21 @@ class _HttpServer |
} |
StreamSubscription<HttpRequest> listen(void onData(HttpRequest event), |
- {Function onError, |
- void onDone(), |
- bool cancelOnError}) { |
- _serverSocket.listen( |
- (Socket socket) { |
- socket.setOption(SocketOption.TCP_NODELAY, true); |
- // Accept the client connection. |
- _HttpConnection connection = new _HttpConnection(socket, this); |
- _idleConnections.add(connection); |
- }, |
- onError: (error, stackTrace) { |
- // Ignore HandshakeExceptions as they are bound to a single request, |
- // and are not fatal for the server. |
- if (error is! HandshakeException) { |
- _controller.addError(error, stackTrace); |
- } |
- }, |
- onDone: _controller.close); |
+ {Function onError, void onDone(), bool cancelOnError}) { |
+ _serverSocket.listen((Socket socket) { |
+ socket.setOption(SocketOption.TCP_NODELAY, true); |
+ // Accept the client connection. |
+ _HttpConnection connection = new _HttpConnection(socket, this); |
+ _idleConnections.add(connection); |
+ }, onError: (error, stackTrace) { |
+ // Ignore HandshakeExceptions as they are bound to a single request, |
+ // and are not fatal for the server. |
+ if (error is! HandshakeException) { |
+ _controller.addError(error, stackTrace); |
+ } |
+ }, onDone: _controller.close); |
return _controller.stream.listen(onData, |
- onError: onError, |
- onDone: onDone, |
- cancelOnError: cancelOnError); |
+ onError: onError, onDone: onDone, cancelOnError: cancelOnError); |
} |
Future close({bool force: false}) { |
@@ -2439,18 +2426,17 @@ class _HttpServer |
// The server listen socket. Untyped as it can be both ServerSocket and |
// SecureServerSocket. |
- final dynamic/*ServerSocket|SecureServerSocket*/ _serverSocket; |
+ final dynamic /*ServerSocket|SecureServerSocket*/ _serverSocket; |
final bool _closeServer; |
// Set of currently connected clients. |
- final LinkedList<_HttpConnection> _activeConnections |
- = new LinkedList<_HttpConnection>(); |
- final LinkedList<_HttpConnection> _idleConnections |
- = new LinkedList<_HttpConnection>(); |
+ final LinkedList<_HttpConnection> _activeConnections = |
+ new LinkedList<_HttpConnection>(); |
+ final LinkedList<_HttpConnection> _idleConnections = |
+ new LinkedList<_HttpConnection>(); |
StreamController<HttpRequest> _controller; |
} |
- |
class _ProxyConfiguration { |
static const String PROXY_PREFIX = "PROXY "; |
static const String DIRECT_PREFIX = "DIRECT"; |
@@ -2510,13 +2496,11 @@ class _ProxyConfiguration { |
}); |
} |
- const _ProxyConfiguration.direct() |
- : proxies = const [const _Proxy.direct()]; |
+ const _ProxyConfiguration.direct() : proxies = const [const _Proxy.direct()]; |
final List<_Proxy> proxies; |
} |
- |
class _Proxy { |
final String host; |
final int port; |
@@ -2526,13 +2510,16 @@ class _Proxy { |
const _Proxy(this.host, this.port, this.username, this.password) |
: isDirect = false; |
- const _Proxy.direct() : host = null, port = null, |
- username = null, password = null, isDirect = true; |
+ const _Proxy.direct() |
+ : host = null, |
+ port = null, |
+ username = null, |
+ password = null, |
+ isDirect = true; |
bool get isAuthenticated => username != null; |
} |
- |
class _HttpConnectionInfo implements HttpConnectionInfo { |
InternetAddress remoteAddress; |
int remotePort; |
@@ -2543,15 +2530,14 @@ class _HttpConnectionInfo implements HttpConnectionInfo { |
try { |
_HttpConnectionInfo info = new _HttpConnectionInfo(); |
return info |
- ..remoteAddress = socket.remoteAddress |
- ..remotePort = socket.remotePort |
- ..localPort = socket.port; |
- } catch (e) { } |
+ ..remoteAddress = socket.remoteAddress |
+ ..remotePort = socket.remotePort |
+ ..localPort = socket.port; |
+ } catch (e) {} |
return null; |
} |
} |
- |
class _DetachedSocket extends Stream<List<int>> implements Socket { |
final Stream<List<int>> _incoming; |
final Socket _socket; |
@@ -2559,13 +2545,9 @@ class _DetachedSocket extends Stream<List<int>> implements Socket { |
_DetachedSocket(this._socket, this._incoming); |
StreamSubscription<List<int>> listen(void onData(List<int> event), |
- {Function onError, |
- void onDone(), |
- bool cancelOnError}) { |
+ {Function onError, void onDone(), bool cancelOnError}) { |
return _incoming.listen(onData, |
- onError: onError, |
- onDone: onDone, |
- cancelOnError: cancelOnError); |
+ onError: onError, onDone: onDone, cancelOnError: cancelOnError); |
} |
Encoding get encoding => _socket.encoding; |
@@ -2574,17 +2556,25 @@ class _DetachedSocket extends Stream<List<int>> implements Socket { |
_socket.encoding = value; |
} |
- void write(Object obj) { _socket.write(obj); } |
+ void write(Object obj) { |
+ _socket.write(obj); |
+ } |
- void writeln([Object obj = ""]) { _socket.writeln(obj); } |
+ void writeln([Object obj = ""]) { |
+ _socket.writeln(obj); |
+ } |
- void writeCharCode(int charCode) { _socket.writeCharCode(charCode); } |
+ void writeCharCode(int charCode) { |
+ _socket.writeCharCode(charCode); |
+ } |
void writeAll(Iterable objects, [String separator = ""]) { |
_socket.writeAll(objects, separator); |
} |
- void add(List<int> bytes) { _socket.add(bytes); } |
+ void add(List<int> bytes) { |
+ _socket.add(bytes); |
+ } |
void addError(error, [StackTrace stackTrace]) => |
_socket.addError(error, stackTrace); |
@@ -2593,7 +2583,9 @@ class _DetachedSocket extends Stream<List<int>> implements Socket { |
return _socket.addStream(stream); |
} |
- void destroy() { _socket.destroy(); } |
+ void destroy() { |
+ _socket.destroy(); |
+ } |
Future flush() => _socket.flush(); |
@@ -2616,12 +2608,12 @@ class _DetachedSocket extends Stream<List<int>> implements Socket { |
Map _toJSON(bool ref) { |
return (_socket as dynamic)._toJSON(ref); |
} |
+ |
void set _owner(owner) { |
(_socket as dynamic)._owner = owner; |
} |
} |
- |
class _AuthenticationScheme { |
final int _scheme; |
@@ -2644,7 +2636,6 @@ class _AuthenticationScheme { |
} |
} |
- |
abstract class _Credentials { |
_HttpClientCredentials credentials; |
String realm; |
@@ -2667,11 +2658,11 @@ abstract class _Credentials { |
// now always use UTF-8 encoding. |
_HttpClientDigestCredentials creds = credentials; |
var hasher = new _MD5() |
- ..add(UTF8.encode(creds.username)) |
- ..add([_CharCode.COLON]) |
- ..add(realm.codeUnits) |
- ..add([_CharCode.COLON]) |
- ..add(UTF8.encode(creds.password)); |
+ ..add(UTF8.encode(creds.username)) |
+ ..add([_CharCode.COLON]) |
+ ..add(realm.codeUnits) |
+ ..add([_CharCode.COLON]) |
+ ..add(UTF8.encode(creds.password)); |
ha1 = _CryptoUtils.bytesToHex(hasher.close()); |
} |
} |
@@ -2700,8 +2691,7 @@ class _SiteCredentials extends _Credentials { |
void authorize(HttpClientRequest request) { |
// Digest credentials cannot be used without a nonce from the |
// server. |
- if (credentials.scheme == _AuthenticationScheme.DIGEST && |
- nonce == null) { |
+ if (credentials.scheme == _AuthenticationScheme.DIGEST && nonce == null) { |
return; |
} |
credentials.authorize(this, request); |
@@ -2709,15 +2699,11 @@ class _SiteCredentials extends _Credentials { |
} |
} |
- |
class _ProxyCredentials extends _Credentials { |
String host; |
int port; |
- _ProxyCredentials(this.host, |
- this.port, |
- realm, |
- _HttpClientCredentials creds) |
+ _ProxyCredentials(this.host, this.port, realm, _HttpClientCredentials creds) |
: super(creds, realm); |
bool applies(_Proxy proxy, _AuthenticationScheme scheme) { |
@@ -2728,24 +2714,20 @@ class _ProxyCredentials extends _Credentials { |
void authorize(HttpClientRequest request) { |
// Digest credentials cannot be used without a nonce from the |
// server. |
- if (credentials.scheme == _AuthenticationScheme.DIGEST && |
- nonce == null) { |
+ if (credentials.scheme == _AuthenticationScheme.DIGEST && nonce == null) { |
return; |
} |
credentials.authorizeProxy(this, request); |
} |
} |
- |
abstract class _HttpClientCredentials implements HttpClientCredentials { |
_AuthenticationScheme get scheme; |
void authorize(_Credentials credentials, HttpClientRequest request); |
void authorizeProxy(_ProxyCredentials credentials, HttpClientRequest request); |
} |
- |
-class _HttpClientBasicCredentials |
- extends _HttpClientCredentials |
+class _HttpClientBasicCredentials extends _HttpClientCredentials |
implements HttpClientBasicCredentials { |
String username; |
String password; |
@@ -2775,9 +2757,7 @@ class _HttpClientBasicCredentials |
} |
} |
- |
-class _HttpClientDigestCredentials |
- extends _HttpClientCredentials |
+class _HttpClientDigestCredentials extends _HttpClientCredentials |
implements HttpClientDigestCredentials { |
String username; |
String password; |
@@ -2789,18 +2769,16 @@ class _HttpClientDigestCredentials |
String authorization(_Credentials credentials, _HttpClientRequest request) { |
String requestUri = request._requestUri(); |
_MD5 hasher = new _MD5() |
- ..add(request.method.codeUnits) |
- ..add([_CharCode.COLON]) |
- ..add(requestUri.codeUnits); |
+ ..add(request.method.codeUnits) |
+ ..add([_CharCode.COLON]) |
+ ..add(requestUri.codeUnits); |
var ha2 = _CryptoUtils.bytesToHex(hasher.close()); |
String qop; |
String cnonce; |
String nc; |
var x; |
- hasher = new _MD5() |
- ..add(credentials.ha1.codeUnits) |
- ..add([_CharCode.COLON]); |
+ hasher = new _MD5()..add(credentials.ha1.codeUnits)..add([_CharCode.COLON]); |
if (credentials.qop == "auth") { |
qop = credentials.qop; |
cnonce = _CryptoUtils.bytesToHex(_IOCrypto.getRandomBytes(4)); |
@@ -2808,53 +2786,52 @@ class _HttpClientDigestCredentials |
nc = credentials.nonceCount.toRadixString(16); |
nc = "00000000".substring(0, 8 - nc.length + 1) + nc; |
hasher |
- ..add(credentials.nonce.codeUnits) |
- ..add([_CharCode.COLON]) |
- ..add(nc.codeUnits) |
- ..add([_CharCode.COLON]) |
- ..add(cnonce.codeUnits) |
- ..add([_CharCode.COLON]) |
- ..add(credentials.qop.codeUnits) |
- ..add([_CharCode.COLON]) |
- ..add(ha2.codeUnits); |
+ ..add(credentials.nonce.codeUnits) |
+ ..add([_CharCode.COLON]) |
+ ..add(nc.codeUnits) |
+ ..add([_CharCode.COLON]) |
+ ..add(cnonce.codeUnits) |
+ ..add([_CharCode.COLON]) |
+ ..add(credentials.qop.codeUnits) |
+ ..add([_CharCode.COLON]) |
+ ..add(ha2.codeUnits); |
} else { |
hasher |
- ..add(credentials.nonce.codeUnits) |
- ..add([_CharCode.COLON]) |
- ..add(ha2.codeUnits); |
+ ..add(credentials.nonce.codeUnits) |
+ ..add([_CharCode.COLON]) |
+ ..add(ha2.codeUnits); |
} |
var response = _CryptoUtils.bytesToHex(hasher.close()); |
StringBuffer buffer = new StringBuffer() |
- ..write('Digest ') |
- ..write('username="$username"') |
- ..write(', realm="${credentials.realm}"') |
- ..write(', nonce="${credentials.nonce}"') |
- ..write(', uri="$requestUri"') |
- ..write(', algorithm="${credentials.algorithm}"'); |
+ ..write('Digest ') |
+ ..write('username="$username"') |
+ ..write(', realm="${credentials.realm}"') |
+ ..write(', nonce="${credentials.nonce}"') |
+ ..write(', uri="$requestUri"') |
+ ..write(', algorithm="${credentials.algorithm}"'); |
if (qop == "auth") { |
buffer |
- ..write(', qop="$qop"') |
- ..write(', cnonce="$cnonce"') |
- ..write(', nc="$nc"'); |
+ ..write(', qop="$qop"') |
+ ..write(', cnonce="$cnonce"') |
+ ..write(', nc="$nc"'); |
} |
buffer.write(', response="$response"'); |
return buffer.toString(); |
} |
void authorize(_Credentials credentials, HttpClientRequest request) { |
- request.headers.set(HttpHeaders.AUTHORIZATION, |
- authorization(credentials, request)); |
+ request.headers |
+ .set(HttpHeaders.AUTHORIZATION, authorization(credentials, request)); |
} |
- void authorizeProxy(_ProxyCredentials credentials, |
- HttpClientRequest request) { |
- request.headers.set(HttpHeaders.PROXY_AUTHORIZATION, |
- authorization(credentials, request)); |
+ void authorizeProxy( |
+ _ProxyCredentials credentials, HttpClientRequest request) { |
+ request.headers.set( |
+ HttpHeaders.PROXY_AUTHORIZATION, authorization(credentials, request)); |
} |
} |
- |
class _RedirectInfo implements RedirectInfo { |
final int statusCode; |
final String method; |