Added HTTP chunk support for hyperf/http-message (#4290)

Co-authored-by: 李铭昕 <715557344@qq.com>
Co-authored-by: pandaLIU <563883861@qq.com>
This commit is contained in:
沈唁 2021-11-24 20:20:55 +08:00 committed by GitHub
parent 019c515ff4
commit cc4cf11a4c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 152 additions and 2 deletions

View File

@ -7,6 +7,7 @@
## Added
- [#4284](https://github.com/hyperf/hyperf/pull/4284) Added method `Hyperf\Utils\Network::ip()`.
- [#4290](https://github.com/hyperf/hyperf/pull/4290) Added HTTP chunk support for `hyperf/http-message`.
# v2.2.17 - 2021-11-22

View File

@ -0,0 +1,17 @@
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\HttpMessage\Server\Chunk;
interface Chunkable
{
public function write(string $data): bool;
}

View File

@ -0,0 +1,24 @@
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\HttpMessage\Server\Chunk;
trait HasChunk
{
public function write(string $content): bool
{
if (isset($this->connection) && $this->connection instanceof Chunkable) {
return $this->connection->write($content);
}
return false;
}
}

View File

@ -0,0 +1,34 @@
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\HttpMessage\Server\Connection;
use Hyperf\HttpMessage\Server\Chunk\Chunkable;
use Hyperf\HttpMessage\Server\ConnectionInterface;
use Swoole\Http\Response;
class SwooleConnection implements ConnectionInterface, Chunkable
{
/**
* @var Response
*/
protected $response;
public function __construct(Response $response)
{
$this->response = $response;
}
public function write(string $data): bool
{
return $this->response->write($data);
}
}

View File

@ -0,0 +1,16 @@
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace Hyperf\HttpMessage\Server;
interface ConnectionInterface
{
}

View File

@ -12,10 +12,14 @@ declare(strict_types=1);
namespace Hyperf\HttpMessage\Server;
use Hyperf\HttpMessage\Cookie\Cookie;
use Hyperf\HttpMessage\Server\Chunk\Chunkable;
use Hyperf\HttpMessage\Server\Chunk\HasChunk;
use Hyperf\HttpMessage\Stream\SwooleStream;
class Response extends \Hyperf\HttpMessage\Base\Response
class Response extends \Hyperf\HttpMessage\Base\Response implements Chunkable
{
use HasChunk;
/**
* @var array
*/
@ -26,6 +30,11 @@ class Response extends \Hyperf\HttpMessage\Base\Response
*/
protected $trailers = [];
/**
* @var null|ConnectionInterface
*/
protected $connection;
/**
* Returns an instance with body content.
*/
@ -80,4 +89,15 @@ class Response extends \Hyperf\HttpMessage\Base\Response
{
return $this->trailers;
}
public function setConnection(ConnectionInterface $connection)
{
$this->connection = $connection;
return $this;
}
public function getConnection(): ?ConnectionInterface
{
return $this->connection;
}
}

View File

@ -40,6 +40,11 @@ class ResponseProxyTest extends ResponseTest
parent::testCookies();
}
public function testWrite()
{
$this->markTestSkipped('Response proxy does not support chunk.');
}
protected function newResponse()
{
$response = new ResponseStub();

View File

@ -12,8 +12,11 @@ declare(strict_types=1);
namespace HyperfTest\HttpMessage;
use Hyperf\HttpMessage\Cookie\Cookie;
use Hyperf\HttpMessage\Server\Connection\SwooleConnection;
use Hyperf\HttpMessage\Server\Response;
use Mockery;
use PHPUnit\Framework\TestCase;
use Swoole\Http\Response as SwooleResponse;
/**
* @internal
@ -52,6 +55,18 @@ class ResponseTest extends TestCase
$this->assertSame(['hyperf.io' => ['/' => ['test' => $cookie]]], $response->getCookies());
}
public function testWrite()
{
$content = 'hello';
$swooleResponse = Mockery::mock(SwooleResponse::class);
$swooleResponse->shouldReceive('write')->with($content)->once()->andReturn(true);
$response = $this->newResponse();
$response->setConnection(new SwooleConnection($swooleResponse));
$status = $response->write($content);
$this->assertTrue($status);
}
protected function newResponse()
{
return new Response();

View File

@ -53,6 +53,11 @@ interface ResponseInterface
*/
public function download(string $file, string $name = ''): PsrResponseInterface;
/**
* Chunked transfer encoding.
*/
public function write(string $data): bool;
/**
* Override a response with a cookie.
*/

View File

@ -13,6 +13,7 @@ namespace Hyperf\HttpServer;
use BadMethodCallException;
use Hyperf\HttpMessage\Cookie\Cookie;
use Hyperf\HttpMessage\Server\Chunk\Chunkable;
use Hyperf\HttpMessage\Stream\SwooleFileStream;
use Hyperf\HttpMessage\Stream\SwooleStream;
use Hyperf\HttpServer\Contract\ResponseInterface;
@ -412,6 +413,16 @@ class Response implements PsrResponseInterface, ResponseInterface
return $this->getResponse()->getReasonPhrase();
}
public function write(string $data): bool
{
$response = $this->getResponse();
if ($response instanceof Chunkable) {
return $response->write($data);
}
return false;
}
protected function call($name, $arguments)
{
$response = $this->getResponse();

View File

@ -17,6 +17,7 @@ use Hyperf\Contract\MiddlewareInitializerInterface;
use Hyperf\Contract\OnRequestInterface;
use Hyperf\Dispatcher\HttpDispatcher;
use Hyperf\ExceptionHandler\ExceptionHandlerDispatcher;
use Hyperf\HttpMessage\Server\Connection\SwooleConnection;
use Hyperf\HttpMessage\Server\Request as Psr7Request;
use Hyperf\HttpMessage\Server\Response as Psr7Response;
use Hyperf\HttpServer\Contract\CoreMiddlewareInterface;
@ -165,7 +166,7 @@ class Server implements OnRequestInterface, MiddlewareInitializerInterface
/**
* Initialize PSR-7 Request and Response objects.
* @param mixed $request swoole request or psr server request
* @param mixed $response swoole response or swow session
* @param mixed $response swoole response or swow connection
*/
protected function initRequestAndResponse($request, $response): array
{
@ -175,6 +176,7 @@ class Server implements OnRequestInterface, MiddlewareInitializerInterface
$psr7Request = $request;
} else {
$psr7Request = Psr7Request::loadFromSwooleRequest($request);
$psr7Response->setConnection(new SwooleConnection($response));
}
Context::set(ServerRequestInterface::class, $psr7Request);