private function doPollForCertificate($location)
{
if (!is_string($location)) {
throw new InvalidArgumentException(sprintf("\$location must be of type string, %s given.", gettype($location)));
}
do {
/** @var Response $response */
$response = (yield $this->acmeClient->get($location));
if ($response->getStatus() === 202) {
if (!$response->hasHeader("retry-after")) {
throw new AcmeException("Protocol violation: Response didn't care any retry-after header.");
}
$waitTime = $this->parseRetryAfter($response->getHeader("retry-after")[0]);
$waitTime = min(max($waitTime, 2), 60);
(yield new Pause($waitTime * 1000));
continue;
} elseif ($response->getStatus() === 200) {
$pem = chunk_split(base64_encode($response->getBody()), 64, "\n");
$pem = "-----BEGIN CERTIFICATE-----\n" . $pem . "-----END CERTIFICATE-----\n";
$certificates = [$pem];
// prevent potential infinite loop
$maximumChainLength = 5;
while ($response->hasHeader("link")) {
if (!$maximumChainLength--) {
throw new AcmeException("Too long certificate chain");
}
$links = $response->getHeader("link");
foreach ($links as $link) {
if (preg_match("#<(.*?)>;rel=\"up\"#x", $link, $match)) {
$uri = \Sabre\Uri\resolve($response->getRequest()->getUri(), $match[1]);
$response = (yield $this->acmeClient->get($uri));
$pem = chunk_split(base64_encode($response->getBody()), 64, "\n");
$pem = "-----BEGIN CERTIFICATE-----\n" . $pem . "-----END CERTIFICATE-----\n";
$certificates[] = $pem;
}
}
}
(yield new CoroutineResult($certificates));
return;
}
} while (1);
throw new AcmeException("Couldn't fetch certificate");
}