in lib/src/http_impl.dart [1566:1686]
_HttpClientRequest send(Uri uri, int port, String method, _Proxy proxy) {
if (closed) {
throw 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.
var outgoing = _HttpOutgoing(_socket);
// Create new request object, wrapping the outgoing connection.
var request =
_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");
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}"));
request.headers.set(HttpHeaders.PROXY_AUTHORIZATION, "Basic $auth");
} else if (!proxy.isDirect && _httpClient._proxyCredentials.isNotEmpty) {
proxyCreds = _httpClient._findProxyCredentials(proxy);
if (proxyCreds != null) {
proxyCreds.authorize(request);
}
}
if (uri.userInfo != null && uri.userInfo.isNotEmpty) {
// If the URL contains user information use that for basic
// authorization.
String auth = CryptoUtils.bytesToBase64(utf8.encode(uri.userInfo));
request.headers.set(HttpHeaders.AUTHORIZATION, "Basic $auth");
} else {
// Look for credentials.
creds = _httpClient._findCredentials(uri);
if (creds != null) {
creds.authorize(request);
}
}
// 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 = Completer<HttpIncoming>();
// 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 =
HeaderValueImpl.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 =
HeaderValueImpl.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 HttpException("Connection closed before data was received",
uri: uri);
}, test: (error) => error is StateError).catchError(
(error, StackTrace 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;
}