я построил себе простой объект запроса HTTP, очень простойPHP fgets работает на неопределенный срок
class Request {
protected $hostname;
protected $port = 80;
protected $method = 'GET';
protected $uri = '/';
protected $headers = array();
protected $body;
protected $handle;
protected $response;
public function __construct() {
$cookies = null;
foreach (\Cookie::getAll() as $k => $v) {
$cookies .= urlencode($k) . '=' . urlencode($v) . '; ';
}
$this->setHeader('Cookie', substr($cookies, 0, -2));
}
public function setHostname($name, $ssl = false) {
if (filter_var(gethostbyname($name), FILTER_VALIDATE_IP)) {
$this->hostname = ($ssl ? 'ssl://' : null) . $name;
$this->setHeader('Host', $name);
return true;
}
return false;
}
public function setPort($port) {
if ($port >= 1 && $port <= 65535) {
$this->port = (int)$port;
return true;
}
return false;
}
public function setMethod($method) {
$methods = [
'GET' => true,
'POST' => true,
'PUT' => true,
'DELETE' => true
];
if (isset($methods[$method])) {
$this->method = strtoupper($method);
return true;
}
return false;
}
public function setUri($uri) {
$this->uri = $uri;
return true;
}
public function setHeader($key, $value) {
$this->headers[$key] = $value;
return true;
}
public function removeHeader($key) {
unset($this->headers[$key]);
return true;
}
public function setBody($body) {
$this->body = $body;
return true;
}
public function send($async = false, $timeout = 30) {
$errno = null;
$errstr = null;
$this->setHeader('Content-Length', strlen($this->body));
if($async){
$this->setHeader('Connection', 'Close');
}
$this->response = null;
$this->handle = fsockopen($this->hostname, $this->port, $errno, $errstr, $timeout);
if (!$this->handle) {
throw new \Exception($errstr, $errno);
}
$headers = null;
foreach ($this->headers as $key => $value) {
$headers .= $key . ': ' . $value . "\r\n";
}
$request = "{$this->method} {$this->uri} HTTP/1.1\r\n{$headers}\r\n" . $this->body;
fwrite($this->handle, $request);
if ($async) {
fclose($this->handle);
return;
}
while (!feof($this->handle)) {
echo $this->response . ' dgd<br/><br/><br/>';
$this->response .= fgets($this->handle, 8192);
}
fclose($this->handle);
}
public function getResponse() {
return $this->response;
}
}
Когда я посылаю «асинхронный» нет никаких проблем, но когда я пытаюсь получить ответ я получаю максимальное время выполнения превышено ошибка. Я добавил эхо в цикл чтения ответов для отладки, и он запускается только один раз. В чем проблема?
$r = new \Request();
$r->setHostname('localhost');
$r->setUri('/test.php');
$r->send();
echo "<pre>" . print_r($r, true) . "</pre>";
test.php
echo 'Test complete.';
источник Ответ первоначального запроса
dgd<br/><br/><br/><br />
<b>Fatal error</b>: Maximum execution time of 30 seconds exceeded in <b>....\Request.php</b> on line <b>98</b><br />
где линия 98 является
$this->response .= fgets($this->handle, 8192);
Я все для выяснения того, как работает материал, но создание собственной библиотеки HTTP не так просто, как вам кажется.Вам также нужно учитывать, что делать, когда вы получаете заголовки '302',' 301', '200 CONTINUE' и т. Д. Есть ли причина, по которой вы не можете использовать cURL или жужжать? – h2ooooooo
Меня это не касается, потому что цель этого объекта - отправлять запросы только моему приложению, и я знаю, какими будут ответы. На данный момент проблема заключается в том, что я не могу прочитать ответ. @ h2ooooooo относительно вашего вопроса - я решил не использовать другие библиотеки именно из-за того, что они более сложны и созданы для обработки различных ситуаций, в то время как мне не нужны все эти функции для моих целей. –
@KarelKubat Я согласен, что имя может быть немного запутанным, в основном это означает отправить запрос и не ждать ответа, с идеей не замедлять реакцию клиента на первоначальный запрос. Что касается 'feof' на закрытых дескрипторах, то невозможно закрыть дескриптор, потому что если' async' истинно, тогда функция вернется, прежде чем попасть в 'feof' –