public function checkout($uri, array $options = [])
{
// Normalize away any IPv6 brackets -- socket resolution will handle that
$uri = str_replace(['[', ']'], '', $uri);
$uriParts = @parse_url($uri);
$scheme = isset($uriParts['scheme']) ? $uriParts['scheme'] : null;
$host = $uriParts['host'];
$port = $uriParts['port'];
$options = $options ? array_merge($this->options, $options) : $this->options;
if ($scheme === 'http') {
$proxy = $options[self::OP_PROXY_HTTP];
} elseif ($scheme === 'https') {
$proxy = $options[self::OP_PROXY_HTTPS];
} else {
return new Failure(new \DomainException('Either http:// or https:// URI scheme required for HTTP socket checkout'));
}
// The underlying TCP pool will ignore the URI fragment when connecting but retain it in the
// name when tracking hostname connection counts. This allows us to expose host connection
// limits transparently even when connecting through a proxy.
$authority = "{$host}:{$port}";
$uri = $proxy ? "tcp://{$proxy}#{$authority}" : "tcp://{$authority}";
$promisor = new Deferred();
$futureCheckout = $this->sockPool->checkout($uri, $options);
$futureCheckout->when(function ($error, $socket) use($promisor, $proxy, $authority) {
if ($error) {
$promisor->fail($error);
} elseif ($proxy) {
$this->tunnelThroughProxy($promisor, $socket, $authority);
} else {
$promisor->succeed($socket);
}
});
return $promisor->promise();
}