Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 17 additions & 5 deletions src/HttpRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Yurun\Util\YurunHttp\Attributes;
use Yurun\Util\YurunHttp\Http\Psr7\Consts\MediaType;
use Yurun\Util\YurunHttp\Http\Psr7\UploadedFile;
use Yurun\Util\YurunHttp\Http\Psr7\Uri;
use Yurun\Util\YurunHttp\Http\Request;

class HttpRequest
Expand Down Expand Up @@ -448,6 +449,10 @@ public function rawHeaders($headers)
$thisHeaders = &$this->headers;
foreach ($headers as $header)
{
if (!str_contains($header, ':'))
{
continue;
}
$list = explode(':', $header, 2);
$thisHeaders[trim($list[0])] = trim($list[1]);
}
Expand All @@ -464,6 +469,10 @@ public function rawHeaders($headers)
*/
public function rawHeader($header)
{
if (!str_contains($header, ':'))
{
return $this;
}
$list = explode(':', $header, 2);
$this->headers[trim($list[0])] = trim($list[1]);

Expand Down Expand Up @@ -1014,15 +1023,18 @@ public function get($url = null, $requestBody = null)
{
if (!empty($requestBody))
{
if (strpos($url, '?'))
if (null === $url)
{
$url .= '&';
$url = $this->url;
}
else
$uri = new Uri($url);
$query = $uri->getQuery();
if ('' !== $query)
{
$url .= '?';
$query .= '&';
}
$url .= http_build_query($requestBody, '', '&');
$query .= http_build_query($requestBody, '', '&');
$url = (string) $uri->withQuery($query);
}

return $this->send($url, [], 'GET');
Expand Down
13 changes: 10 additions & 3 deletions src/YurunHttp/Handler/Curl.php
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,7 @@ private function parseHeaderOneRequest($headers)
for ($i = 1; $i < $count; ++$i)
{
$line = trim($headers[$i]);
if (empty($line) || false == strstr($line, ':'))
if (empty($line) || false === strstr($line, ':'))
{
continue;
}
Expand Down Expand Up @@ -570,6 +570,10 @@ private function parseOptions(&$request, &$options, &$headers = null, &$saveFile
$saveFilePath .= basename($request->getUri()->__toString());
}
$saveFileFp = fopen($saveFilePath, $request->getAttribute(Attributes::SAVE_FILE_MODE, 'w+'));
if (false === $saveFileFp)
{
throw new \RuntimeException(sprintf('fopen save file failed: %s', $saveFilePath));
}
$options[\CURLOPT_HEADER] = false;
$options[\CURLOPT_RETURNTRANSFER] = false;
$options[\CURLOPT_FILE] = $saveFileFp;
Expand Down Expand Up @@ -670,7 +674,7 @@ private function parseNetwork(&$request, &$options)
{
// 用户名密码处理
$username = $request->getAttribute(Attributes::USERNAME);
if (null != $username)
if (null !== $username)
{
$userPwd = $username . ':' . $request->getAttribute(Attributes::PASSWORD, '');
}
Expand Down Expand Up @@ -762,7 +766,10 @@ public function coBatch($requests, $timeout = null)
{
break;
}
usleep(5000); // 每次延时 5 毫秒
if (-1 === curl_multi_select($mh, 0.5))
{
usleep(250);
}
}
else
{
Expand Down
1 change: 0 additions & 1 deletion src/YurunHttp/Handler/Swoole.php
Original file line number Diff line number Diff line change
Expand Up @@ -810,7 +810,6 @@ public function coBatch($requests, $timeout = null)
$request1 = $handler->sendDefer($request1);
}
unset($request1);
$beginTime = microtime(true);
$recvTimeout = null;
foreach ($requests as $i => $request2)
{
Expand Down
8 changes: 6 additions & 2 deletions src/YurunHttp/Handler/Swoole/SwooleHttp2ConnectionPool.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ class SwooleHttp2ConnectionPool extends BaseConnectionPool
public function __construct($config)
{
parent::__construct($config);
$this->channel = new Channel(1024);
$maxConnections = $config->getMaxConnections();
$capacity = $maxConnections > 0 ? $maxConnections : 1024;
$this->channel = new Channel($capacity);
}

/**
Expand All @@ -41,7 +43,9 @@ public function close()
{
$connections = $this->connections;
$this->connections = [];
$this->channel = new Channel(1024);
$maxConnections = $this->config->getMaxConnections();
$capacity = $maxConnections > 0 ? $maxConnections : 1024;
$this->channel = new Channel($capacity);
foreach ($connections as $connection)
{
$connection->close();
Expand Down
8 changes: 6 additions & 2 deletions src/YurunHttp/Handler/Swoole/SwooleHttpConnectionPool.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ class SwooleHttpConnectionPool extends BaseConnectionPool
public function __construct($config)
{
parent::__construct($config);
$this->channel = new Channel(1024);
$maxConnections = $config->getMaxConnections();
$capacity = $maxConnections > 0 ? $maxConnections : 1024;
$this->channel = new Channel($capacity);
}

/**
Expand All @@ -41,7 +43,9 @@ public function close()
{
$connections = $this->connections;
$this->connections = [];
$this->channel = new Channel(1024);
$maxConnections = $this->config->getMaxConnections();
$capacity = $maxConnections > 0 ? $maxConnections : 1024;
$this->channel = new Channel($capacity);
foreach ($connections as $connection)
{
$connection->close();
Expand Down
93 changes: 93 additions & 0 deletions tests/unit/HttpRequestTest/HttpRequestTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -825,4 +825,97 @@ public function testCookieJar(): void
$this->assertEquals('3', isset($data['cookie']['c']) ? $data['cookie']['c'] : null);
});
}

/**
* rawHeader/rawHeaders 跳过不含冒号的行(避免未定义索引警告).
*
* @return void
*/
public function testRawHeaderWithoutColon(): void
{
$this->call(function () {
$http = new HttpRequest();
$http->rawHeader('X-NoColon')
->rawHeaders([
'X-Valid: 1',
'X-NoColon2',
]);
$this->assertArrayHasKey('X-Valid', $http->headers);
$this->assertEquals('1', $http->headers['X-Valid']);
$this->assertArrayNotHasKey('X-NoColon', $http->headers);
$this->assertArrayNotHasKey('X-NoColon2', $http->headers);
});
}

/**
* get() 在已有查询参数时正确拼接请求体.
*
* @return void
*/
public function testGetWithExistingQueryAndBody(): void
{
$this->call(function () {
$http = new HttpRequest();
$time = time();
$response = $http->get($this->host . '?a=info', [
'time' => $time,
]);
$this->assertResponse($response);
$data = $response->json(true);
$this->assertEquals('GET', isset($data['method']) ? $data['method'] : null);
$this->assertEquals($time, isset($data['get']['time']) ? $data['get']['time'] : null);
});
}

/**
* 保存文件 fopen 失败时抛出 RuntimeException.
*
* @return void
*/
public function testSaveFileFopenFailureThrows(): void
{
$this->expectException(\RuntimeException::class);
$this->call(function () {
YurunHttp::setDefaultHandler(\Yurun\Util\YurunHttp\Handler\Curl::class);
set_error_handler(function () {
return true;
}, \E_WARNING);
try
{
$http = new HttpRequest();
$http->saveFile('/path/does/not/exist/yurunhttp_test_save.txt')
->get($this->host);
}
finally
{
restore_error_handler();
}
});
}

/**
* 连接池 Channel 容量等于最大连接数,未配置时为 1024.
*
* @return void
*/
public function testConnectionPoolChannelCapacity(): void
{
if (!\extension_loaded('swoole'))
{
$this->markTestSkipped('Requires ext/swoole');
}
$config = new \Yurun\Util\YurunHttp\Pool\Config\PoolConfig($this->host, 5, 0.0);
$pool = new \Yurun\Util\YurunHttp\Handler\Swoole\SwooleHttpConnectionPool($config);
$ref = new \ReflectionProperty($pool, 'channel');
$ref->setAccessible(true);
$channel = $ref->getValue($pool);
$this->assertEquals(5, $channel->capacity);

$config2 = new \Yurun\Util\YurunHttp\Pool\Config\PoolConfig($this->host, 0, 0.0);
$pool2 = new \Yurun\Util\YurunHttp\Handler\Swoole\SwooleHttpConnectionPool($config2);
$ref2 = new \ReflectionProperty($pool2, 'channel');
$ref2->setAccessible(true);
$channel2 = $ref2->getValue($pool2);
$this->assertEquals(1024, $channel2->capacity);
}
}
Loading