feat: 实现了通过中间件设置是否 restful 的逻辑

This commit is contained in:
李东云
2023-03-10 18:29:41 +08:00
parent 2d2a535fd2
commit 2d2148f3ec
6 changed files with 257 additions and 0 deletions

View File

@@ -28,6 +28,9 @@ use Singularity\HDK\Core\Service\UtilsService;
* @author 李东云<dongyun.li@luxcreo.cn>
* Powered by PhpStorm
* Created on 2022/4/29
*
* @deprecated
* @see CommonCoreMiddleware
*/
class ClassicCoreMiddleware extends CoreMiddleware
{

View File

@@ -0,0 +1,30 @@
<?php
/**
* ClassicStyleMiddleware.php@HDK-Core
*
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
* Powered by PhpStorm
* Created on 2023/3/10
*/
namespace Singularity\HDK\Core\Middleware;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Singularity\HDK\Core\Service\ApiStyleService;
class ClassicStyleMiddleware implements \Psr\Http\Server\MiddlewareInterface
{
public function __construct(protected ApiStyleService $apiStyleService)
{
}
/**
* @inheritDoc
*/
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$this->apiStyleService->set(ApiStyleService::CLASSIC);
}
}

View File

@@ -0,0 +1,156 @@
<?php
/**
* ClassicCoreMiddleware.php@hyperf-development-kit
*
* @author 李东云<dongyun.li@luxcreo.cn>
* Powered by PhpStorm
* Created on 2022/4/29
*/
namespace Singularity\HDK\Core\Middleware;
use Hyperf\Contract\Arrayable;
use Hyperf\Contract\Jsonable;
use Hyperf\Contract\LengthAwarePaginatorInterface;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpMessage\Stream\SwooleStream;
use Hyperf\HttpServer\CoreMiddleware;
use Hyperf\Utils\Codec\Json;
use Lmc\HttpConstants\Header;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Singularity\HDK\Core\Service\ApiStyleService;
use Singularity\HDK\Core\Service\UtilsService;
/**
* Singularity\HDK\Core\Middleware\CommonCoreMiddleware@HDK-Core
*
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
* Powered by PhpStorm
* Created on 2023/3/10
*/
class CommonCoreMiddleware extends CoreMiddleware
{
#[Inject]
private UtilsService $utilsService;
#[Inject]
private ApiStyleService $apiStyleService;
/**
* Transfer the non-standard response content to a standard response object.
* @template TKey of array-key
* @template TValue
* @param null|array<TKey, TValue>|Arrayable<TKey, TValue>|Jsonable|string $response
*/
protected function transferToClassicResponse($response, ServerRequestInterface $request): ResponseInterface
{
$code_name = config('common.response.code_name');
$message_name = config('common.response.message_name');
$data_name = config('common.response.data_name');
// 分页数据
if ($response instanceof LengthAwarePaginatorInterface) {
$paginator = $response;
$fact_response = $this->response()->withHeader('Per-Page', (string)$paginator->perPage())->withHeader(
'Total',
(string)$paginator->total()
)->withHeader('Current-Page', (string)$paginator->currentPage())->withHeader(
'Total-Pages',
(string)$paginator->hasPages()
);
$fact_response = $this->utilsService->extendLinkToHeader($fact_response, $paginator->nextPageUrl(), 'next');
$fact_response = $this->utilsService->extendLinkToHeader(
$fact_response,
$paginator->url($paginator->lastPage()),
'last'
);
$fact_response = $this->utilsService->extendLinkToHeader($fact_response, $paginator->url(1), 'first');
$fact_response = $this->utilsService->extendLinkToHeader(
$fact_response,
$paginator->previousPageUrl(),
'prev'
);
return $fact_response->withAddedHeader(Header::CONTENT_TYPE, 'application/json')->withBody(
new SwooleStream(
Json::encode(
[
$code_name => 200,
$message_name => 'ok',
$data_name => $response->items(),
'meta' => [
'currentPage' => $paginator->currentPage(),
'lastPage' => $paginator->lastPage(),
'perPage' => $paginator->perPage(),
'total' => $paginator->total(),
],
]
)
)
);
}
// 普通数组
if (is_array($response) || $response instanceof Arrayable) {
$response = [$code_name => 200, $message_name => 'ok', $data_name => $response];
return $this->response()->withAddedHeader(Header::CONTENT_TYPE, 'application/json')->withBody(
new SwooleStream(Json::encode($response))
);
}
// 可 Json 化的数据结构
if ($response instanceof Jsonable) {
$response = [$code_name => 200, $message_name => 'ok', $data_name => Json::decode((string)$response)];
return $this->response()->withAddedHeader(Header::CONTENT_TYPE, 'application/json')->withBody(
new SwooleStream(Json::encode($response))
);
}
// 其他默认按字符串处理
return $this->response()->withAddedHeader(Header::CONTENT_TYPE, 'text/plain')->withBody(
new SwooleStream((string)$response)
);
}
protected function transferToResponse($response, ServerRequestInterface $request): ResponseInterface
{
$style = $this->apiStyleService->get();
if ($style === ApiStyleService::RESTFUL) {
return $this->transferToRestfulResponse($response, $request);
} else {
return $this->transferToClassicResponse($response, $request);
}
}
/**
* @template TKey of array-key
* @template TValue
* @param null|array<TKey, TValue>|Arrayable<TKey, TValue>|Jsonable|string $response
* @param ServerRequestInterface $request
* @return ResponseInterface
*/
protected function transferToRestfulResponse($response, ServerRequestInterface $request): ResponseInterface
{
// 分页数据
if ($response instanceof LengthAwarePaginatorInterface) {
$fact_response = $this->response()
->withHeader('Per-Page', (string)$response->perPage())
->withHeader('Total', (string)$response->total())
->withHeader('Current-Page', (string)$response->currentPage())
->withHeader('Total-Pages', (string)$response->hasPages());
$fact_response = $this->utilsService->extendLinkToHeader($fact_response, $response->nextPageUrl(), 'next');
$fact_response = $this->utilsService->extendLinkToHeader(
$fact_response,
$response->url($response->lastPage()),
'last'
);
$fact_response = $this->utilsService->extendLinkToHeader($fact_response, $response->url(1), 'first');
return $this->utilsService->extendLinkToHeader(
$fact_response,
$response->previousPageUrl(),
'prev'
);
}
return parent::transferToResponse($response, $request);
}
}

View File

@@ -0,0 +1,31 @@
<?php
/**
* ClassicStyleMiddleware.php@HDK-Core
*
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
* Powered by PhpStorm
* Created on 2023/3/10
*/
namespace Singularity\HDK\Core\Middleware;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Singularity\HDK\Core\Service\ApiStyleService;
class RestStyleMiddleware implements MiddlewareInterface
{
public function __construct(protected ApiStyleService $apiStyleService)
{
}
/**
* @inheritDoc
*/
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$this->apiStyleService->set(ApiStyleService::RESTFUL);
}
}

View File

@@ -24,6 +24,9 @@ use Singularity\HDK\Core\Service\UtilsService;
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
* Powered by PhpStorm
* Created on 2023/1/14
*
* @deprecated
* @see CommonCoreMiddleware
*/
class RestfulCoreMiddleware extends CoreMiddleware
{

View File

@@ -0,0 +1,34 @@
<?php
/**
* ApiStyleService.php@HDK-Core
*
* @author 李东云 <Dongyun.Li@LuxCreo.Ai>
* Powered by PhpStorm
* Created on 2023/3/10
*/
namespace Singularity\HDK\Core\Service;
use Hyperf\Context\Context;
class ApiStyleService
{
public const RESTFUL = 'restful';
public const CLASSIC = 'classic';
public function __construct()
{
Context::set(self::class, config('common.response.restful') ? self::RESTFUL : self::CLASSIC);
}
public function set($style): static
{
Context::set(self::class, $style === self::RESTFUL ? self::RESTFUL : self::CLASSIC);
return $this;
}
public function get(): string
{
return Context::get(self::class);
}
}