public function readRequest(Socket $socket, float $timeout = 0) : \Generator
{
$buffer = new Buffer();
try {
do {
$buffer->push(yield from $socket->read(0, null, $timeout));
} while (false === ($position = $buffer->search("\r\n")) && $buffer->getLength() < $this->maxStartLineLength);
if (false === $position) {
throw new MessageException(Response::REQUEST_HEADER_TOO_LARGE, sprintf('Message start line exceeded maximum size of %d bytes.', $this->maxStartLineLength));
}
$line = $buffer->shift($position + 2);
if (!preg_match("/^([A-Z]+) (\\S+) HTTP\\/(\\d+(?:\\.\\d+)?)\r\n\$/i", $line, $matches)) {
throw new ParseException('Could not parse start line.');
}
$method = $matches[1];
$target = $matches[2];
$protocol = $matches[3];
$headers = (yield from $this->readHeaders($buffer, $socket, $timeout));
} finally {
$socket->unshift((string) $buffer);
}
if ('/' === $target[0]) {
// origin-form
$uri = new BasicUri($this->filterHost($this->findHost($headers)) . $target);
$target = null;
// Empty request target since it was a path.
} elseif ('*' === $target) {
// asterisk-form
$uri = new BasicUri($this->filterHost($this->findHost($headers)));
} elseif (preg_match('/^[A-Za-z0-9]+:\\/\\//', $target)) {
// absolute-form
$uri = new BasicUri($target);
} else {
// authority-form
$uri = new BasicUri($this->filterHost($target));
}
return new BasicRequest($method, $uri, $headers, $socket, $target, $protocol);
}