q
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "game-worker/kiri-router",
|
||||
"description": "kiri router",
|
||||
"authors": [
|
||||
{
|
||||
"name": "XiangLin",
|
||||
"email": "as2252258@163.com"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"php": ">=8.0",
|
||||
"composer-runtime-api": "^2.0",
|
||||
"psr/http-server-middleware": "^1.0",
|
||||
"psr/http-message": "^1.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Kiri\\Router": "./src"
|
||||
}
|
||||
},
|
||||
"require-dev": {
|
||||
}
|
||||
}
|
||||
@@ -5,4 +5,37 @@ namespace Kiri\Router;
|
||||
class ActionManager
|
||||
{
|
||||
|
||||
|
||||
private static array $array = [];
|
||||
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
* @param string $method
|
||||
* @param Handler $handler
|
||||
* @return void
|
||||
*/
|
||||
public static function add(string $class, string $method, Handler $handler): void
|
||||
{
|
||||
if (!isset(static::$array[$class])) {
|
||||
static::$array[$class] = [$method => []];
|
||||
}
|
||||
static::$array[$class][$method] = $handler;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
* @param string $method
|
||||
* @return array|null
|
||||
*/
|
||||
public static function get(string $class, string $method): ?Handler
|
||||
{
|
||||
if (isset(static::$array[$class])) {
|
||||
return static::$array[$class][$method] ?? null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Message\Aspect;
|
||||
namespace Kiri\Router\Aspect;
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Message\Aspect;
|
||||
namespace Kiri\Router\Aspect;
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Message\Aspect;
|
||||
namespace Kiri\Router\Aspect;
|
||||
|
||||
interface OnAspectInterface
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Message\Aspect;
|
||||
namespace Kiri\Router\Aspect;
|
||||
|
||||
interface OnJoinPointInterface
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Message\Aspect;
|
||||
namespace Kiri\Router\Aspect;
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,42 @@
|
||||
|
||||
namespace Kiri\Router\Base;
|
||||
|
||||
class AbstractHandler
|
||||
use Kiri\Inject\Route\TestResponse;
|
||||
use Kiri\Router\Handler;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
abstract class AbstractHandler
|
||||
{
|
||||
|
||||
|
||||
public int $offset = 0;
|
||||
|
||||
|
||||
/**
|
||||
* @param array $middlewares
|
||||
* @param Handler $handler
|
||||
*/
|
||||
public function __construct(public array $middlewares, public Handler $handler)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param ServerRequestInterface $request
|
||||
* @return ResponseInterface
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
public function execute(ServerRequestInterface $request): ResponseInterface
|
||||
{
|
||||
if (!isset($this->middlewares[$this->offset])) {
|
||||
return $this->handler->handle($request);
|
||||
}
|
||||
|
||||
$middleware = di($this->middlewares[$this->offset]);
|
||||
$this->offset += 1;
|
||||
|
||||
return $middleware->process($request);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace Kiri\Message\Handler;
|
||||
namespace Kiri\Router\Base;
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Message\Handler;
|
||||
namespace Kiri\Router\Base;
|
||||
|
||||
class ClosureController extends Controller
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Kiri\Message\Handler;
|
||||
namespace Kiri\Router\Base;
|
||||
|
||||
|
||||
use Kiri;
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Message\Handler;
|
||||
namespace Kiri\Router\Base;
|
||||
|
||||
use Exception;
|
||||
use Kiri\Message\Handler\Abstracts\Middleware;
|
||||
use Kiri\Message\ServerRequest;
|
||||
use Kiri\Router\ServerRequest;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\MiddlewareInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class CoreMiddleware extends Middleware
|
||||
class CoreMiddleware implements MiddlewareInterface
|
||||
{
|
||||
|
||||
|
||||
@@ -25,12 +25,11 @@ class CoreMiddleware extends Middleware
|
||||
*/
|
||||
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
|
||||
{
|
||||
$requestMethod = $request->getAccessControlRequestMethod();
|
||||
$allowHeaders = $request->getAccessControlAllowHeaders();
|
||||
|
||||
$this->response->withAccessControlAllowOrigin('*')->withAccessControlRequestMethod($requestMethod)
|
||||
->withAccessControlAllowHeaders($allowHeaders);
|
||||
|
||||
/** @var ResponseInterface $response */
|
||||
$response = \Kiri::service()->get('response');
|
||||
$response->withHeader('Access-Control-Allow-Headers', $request->header('Access-Control-Allow-Headers'))
|
||||
->withHeader('Access-Control-Request-Method', $request->header('Access-Control-Allow-Origin'))
|
||||
->withHeader('Access-Control-Allow-Origin', $request->header('Access-Control-Allow-Headers'));
|
||||
return $handler->handle($request);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Message\Abstracts;
|
||||
namespace Kiri\Router\Base;
|
||||
|
||||
use Kiri\Annotation\Inject;
|
||||
use Kiri\Events\EventDispatch;
|
||||
|
||||
trait EventDispatchHelper
|
||||
{
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Message;
|
||||
namespace Kiri\Router\Base;
|
||||
|
||||
|
||||
use Kiri\Message\Constrict\Response;
|
||||
use Kiri\Message\Constrict\ResponseInterface;
|
||||
use Kiri\Message\Abstracts\ExceptionHandlerInterface;
|
||||
use Kiri\Router\ContentType;
|
||||
use Kiri\Router\Interface\ExceptionHandlerInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Throwable;
|
||||
use Kiri\Router\Constrict\Stream;
|
||||
|
||||
|
||||
/**
|
||||
@@ -18,17 +19,17 @@ class ExceptionHandlerDispatcher implements ExceptionHandlerInterface
|
||||
|
||||
/**
|
||||
* @param Throwable $exception
|
||||
* @param Response $response
|
||||
* @param object $response
|
||||
* @return ResponseInterface
|
||||
*/
|
||||
public function emit(Throwable $exception, Response $response): ResponseInterface
|
||||
public function emit(Throwable $exception, object $response): ResponseInterface
|
||||
{
|
||||
$response->withContentType(ContentType::HTML);
|
||||
$response->withContentType(ContentType::HTML)->withBody(new Stream(jTraceEx($exception, null, true)));
|
||||
if ($exception->getCode() == 404) {
|
||||
return $response->withBody(new Stream($exception->getMessage()))->withStatus(404);
|
||||
return $response->withStatus(404);
|
||||
} else {
|
||||
return $response->withStatus($exception->getCode() == 0 ? 500 : $exception->getCode());
|
||||
}
|
||||
return $response->withBody(new Stream(jTraceEx($exception, null, true)))
|
||||
->withStatus($exception->getCode() == 0 ? 500 : $exception->getCode());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Message\Handler;
|
||||
namespace Kiri\Router\Base;
|
||||
|
||||
use Kiri\Message\Constrict\ResponseInterface;
|
||||
|
||||
|
||||
@@ -2,7 +2,47 @@
|
||||
|
||||
namespace Kiri\Router\Base;
|
||||
|
||||
use Exception;
|
||||
use Kiri\Core\HashMap;
|
||||
use Psr\Http\Server\MiddlewareInterface;
|
||||
|
||||
class Middleware
|
||||
{
|
||||
|
||||
|
||||
public HashMap $map;
|
||||
|
||||
public HashMap $routeMap;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->routeMap = new HashMap();
|
||||
$this->map = new HashMap();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param mixed $middleware
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function addPathMiddleware(string $path, string $middleware): void
|
||||
{
|
||||
if ($this->routeMap->has($path)) {
|
||||
$values = $this->routeMap->get($path);
|
||||
if (in_array($middleware, $values)) {
|
||||
return;
|
||||
}
|
||||
if (!in_array(MiddlewareInterface::class, class_implements($middleware))) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
$this->routeMap->append($path, $middleware);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Message\Handler;
|
||||
namespace Kiri\Router\Base;
|
||||
|
||||
use Kiri\Message\Constrict\ResponseInterface;
|
||||
|
||||
|
||||
+70
-16
@@ -1,13 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Router\Message;
|
||||
namespace Kiri\Router\Constrict;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Psr\Http\Message\MessageInterface;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
|
||||
class Message implements MessageInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private string $version = '1.1';
|
||||
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private array $headers = [];
|
||||
|
||||
|
||||
/**
|
||||
* @var StreamInterface
|
||||
*/
|
||||
private StreamInterface $stream;
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the HTTP protocol version as a string.
|
||||
*
|
||||
@@ -15,9 +34,10 @@ class Message implements MessageInterface
|
||||
*
|
||||
* @return string HTTP protocol version.
|
||||
*/
|
||||
public function getProtocolVersion()
|
||||
public function getProtocolVersion(): string
|
||||
{
|
||||
// TODO: Implement getProtocolVersion() method.
|
||||
return $this->version;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -33,9 +53,11 @@ class Message implements MessageInterface
|
||||
* @param string $version HTTP protocol version
|
||||
* @return static
|
||||
*/
|
||||
public function withProtocolVersion(string $version)
|
||||
public function withProtocolVersion(string $version): static
|
||||
{
|
||||
// TODO: Implement withProtocolVersion() method.
|
||||
$this->version = $version;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,9 +85,10 @@ class Message implements MessageInterface
|
||||
* key MUST be a header name, and each value MUST be an array of strings
|
||||
* for that header.
|
||||
*/
|
||||
public function getHeaders()
|
||||
public function getHeaders(): array
|
||||
{
|
||||
// TODO: Implement getHeaders() method.
|
||||
return $this->headers;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -76,9 +99,10 @@ class Message implements MessageInterface
|
||||
* name using a case-insensitive string comparison. Returns false if
|
||||
* no matching header name is found in the message.
|
||||
*/
|
||||
public function hasHeader(string $name)
|
||||
public function hasHeader(string $name): bool
|
||||
{
|
||||
// TODO: Implement hasHeader() method.
|
||||
return isset($this->headers[$name]) && $this->headers[$name] !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -95,9 +119,15 @@ class Message implements MessageInterface
|
||||
* header. If the header does not appear in the message, this method MUST
|
||||
* return an empty array.
|
||||
*/
|
||||
public function getHeader(string $name)
|
||||
public function getHeader(string $name): array
|
||||
{
|
||||
// TODO: Implement getHeader() method.
|
||||
if (isset($this->headers[$name])) {
|
||||
$header = $this->headers[$name];
|
||||
|
||||
return is_string($header) ? [$header] : $header;
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -119,9 +149,24 @@ class Message implements MessageInterface
|
||||
* concatenated together using a comma. If the header does not appear in
|
||||
* the message, this method MUST return an empty string.
|
||||
*/
|
||||
public function getHeaderLine(string $name)
|
||||
public function getHeaderLine(string $name): string
|
||||
{
|
||||
// TODO: Implement getHeaderLine() method.
|
||||
return implode(';', $this->getHeader($name));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param string|null $default
|
||||
* @return string|null
|
||||
*/
|
||||
public function header(string $name, ?string $default = null): ?string
|
||||
{
|
||||
if (!$this->hasHeader($name)) {
|
||||
return $default;
|
||||
}
|
||||
return $this->getHeaderLine($name);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -137,11 +182,13 @@ class Message implements MessageInterface
|
||||
* @param string $name Case-insensitive header field name.
|
||||
* @param string|string[] $value Header value(s).
|
||||
* @return static
|
||||
* @throws \InvalidArgumentException for invalid header names or values.
|
||||
* @throws InvalidArgumentException for invalid header names or values.
|
||||
*/
|
||||
public function withHeader(string $name, $value)
|
||||
public function withHeader(string $name, $value): static
|
||||
{
|
||||
// TODO: Implement withHeader() method.
|
||||
// TODO: Implement withAddedHeader() method.
|
||||
$this->headers[$name] = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -158,11 +205,13 @@ class Message implements MessageInterface
|
||||
* @param string $name Case-insensitive header field name to add.
|
||||
* @param string|string[] $value Header value(s).
|
||||
* @return static
|
||||
* @throws \InvalidArgumentException for invalid header names or values.
|
||||
* @throws InvalidArgumentException for invalid header names or values.
|
||||
*/
|
||||
public function withAddedHeader(string $name, $value)
|
||||
public function withAddedHeader(string $name, $value): static
|
||||
{
|
||||
// TODO: Implement withAddedHeader() method.
|
||||
$this->headers[$name] = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -177,9 +226,11 @@ class Message implements MessageInterface
|
||||
* @param string $name Case-insensitive header field name to remove.
|
||||
* @return static
|
||||
*/
|
||||
public function withoutHeader(string $name)
|
||||
public function withoutHeader(string $name): static
|
||||
{
|
||||
// TODO: Implement withoutHeader() method.
|
||||
unset($this->headers[$name]);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -187,9 +238,10 @@ class Message implements MessageInterface
|
||||
*
|
||||
* @return StreamInterface Returns the body as a stream.
|
||||
*/
|
||||
public function getBody()
|
||||
public function getBody(): StreamInterface
|
||||
{
|
||||
// TODO: Implement getBody() method.
|
||||
return $this->stream;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -203,10 +255,12 @@ class Message implements MessageInterface
|
||||
*
|
||||
* @param StreamInterface $body Body.
|
||||
* @return static
|
||||
* @throws \InvalidArgumentException When the body is not valid.
|
||||
* @throws InvalidArgumentException When the body is not valid.
|
||||
*/
|
||||
public function withBody(StreamInterface $body)
|
||||
public function withBody(StreamInterface $body): static
|
||||
{
|
||||
// TODO: Implement withBody() method.
|
||||
$this->stream = $body;
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Router\Message;
|
||||
namespace Kiri\Router\Constrict;
|
||||
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Psr\Http\Message\UriInterface;
|
||||
@@ -8,6 +8,19 @@ use Psr\Http\Message\UriInterface;
|
||||
class Request extends Message implements RequestInterface
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private string $method;
|
||||
|
||||
|
||||
/**
|
||||
* @var UriInterface
|
||||
*/
|
||||
private UriInterface $uri;
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the message's request target.
|
||||
*
|
||||
@@ -24,9 +37,23 @@ class Request extends Message implements RequestInterface
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRequestTarget()
|
||||
public function getRequestTarget(): string
|
||||
{
|
||||
// TODO: Implement getRequestTarget() method.
|
||||
return (string)$this->getUri();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $headers
|
||||
* @return $this
|
||||
*/
|
||||
public function withHeaders(array $headers): static
|
||||
{
|
||||
foreach ($headers as $key => $header) {
|
||||
$this->withHeader($key, [$header]);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -46,9 +73,10 @@ class Request extends Message implements RequestInterface
|
||||
* @param string $requestTarget
|
||||
* @return static
|
||||
*/
|
||||
public function withRequestTarget(string $requestTarget)
|
||||
public function withRequestTarget(string $requestTarget): static
|
||||
{
|
||||
// TODO: Implement withRequestTarget() method.
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -56,9 +84,10 @@ class Request extends Message implements RequestInterface
|
||||
*
|
||||
* @return string Returns the request method.
|
||||
*/
|
||||
public function getMethod()
|
||||
public function getMethod(): string
|
||||
{
|
||||
// TODO: Implement getMethod() method.
|
||||
return $this->method;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -76,9 +105,11 @@ class Request extends Message implements RequestInterface
|
||||
* @return static
|
||||
* @throws \InvalidArgumentException for invalid HTTP methods.
|
||||
*/
|
||||
public function withMethod(string $method)
|
||||
public function withMethod(string $method): static
|
||||
{
|
||||
// TODO: Implement withMethod() method.
|
||||
$this->method = $method;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,9 +121,10 @@ class Request extends Message implements RequestInterface
|
||||
* @return UriInterface Returns a UriInterface instance
|
||||
* representing the URI of the request.
|
||||
*/
|
||||
public function getUri()
|
||||
public function getUri(): UriInterface
|
||||
{
|
||||
// TODO: Implement getUri() method.
|
||||
return $this->uri;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -125,8 +157,10 @@ class Request extends Message implements RequestInterface
|
||||
* @param bool $preserveHost Preserve the original state of the Host header.
|
||||
* @return static
|
||||
*/
|
||||
public function withUri(UriInterface $uri, bool $preserveHost = false)
|
||||
public function withUri(UriInterface $uri, bool $preserveHost = false): static
|
||||
{
|
||||
// TODO: Implement withUri() method.
|
||||
$this->uri = $uri;
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Router\Message;
|
||||
namespace Kiri\Router\Constrict;
|
||||
|
||||
use Kiri\Router\ContentType;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
class Response extends Message implements ResponseInterface
|
||||
{
|
||||
|
||||
|
||||
private int $code = 200;
|
||||
|
||||
|
||||
private string $reasonPhrase;
|
||||
|
||||
|
||||
/**
|
||||
* @param ContentType $type
|
||||
* @return $this
|
||||
*/
|
||||
public function withContentType(ContentType $type): static
|
||||
{
|
||||
$this->withHeader('Content-Type', $type->name);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the response status code.
|
||||
*
|
||||
@@ -15,9 +33,10 @@ class Response extends Message implements ResponseInterface
|
||||
*
|
||||
* @return int Status code.
|
||||
*/
|
||||
public function getStatusCode()
|
||||
public function getStatusCode(): int
|
||||
{
|
||||
// TODO: Implement getStatusCode() method.
|
||||
return $this->code;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -40,9 +59,12 @@ class Response extends Message implements ResponseInterface
|
||||
* @return static
|
||||
* @throws \InvalidArgumentException For invalid status code arguments.
|
||||
*/
|
||||
public function withStatus(int $code, string $reasonPhrase = '')
|
||||
public function withStatus(int $code, string $reasonPhrase = ''): static
|
||||
{
|
||||
// TODO: Implement withStatus() method.
|
||||
$this->code = $code;
|
||||
$this->reasonPhrase = $reasonPhrase;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,8 +80,9 @@ class Response extends Message implements ResponseInterface
|
||||
* @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
|
||||
* @return string Reason phrase; must return an empty string if none present.
|
||||
*/
|
||||
public function getReasonPhrase()
|
||||
public function getReasonPhrase(): string
|
||||
{
|
||||
// TODO: Implement getReasonPhrase() method.
|
||||
return $this->reasonPhrase;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Router\Message;
|
||||
namespace Kiri\Router\Constrict;
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class ServerRequest extends Request implements ServerRequestInterface
|
||||
{
|
||||
|
||||
|
||||
private array $posts = [];
|
||||
|
||||
private array $query = [];
|
||||
|
||||
|
||||
private array $cookies = [];
|
||||
|
||||
private array $server = [];
|
||||
|
||||
private array $files = [];
|
||||
|
||||
/**
|
||||
* Retrieve server parameters.
|
||||
*
|
||||
@@ -16,9 +28,10 @@ class ServerRequest extends Request implements ServerRequestInterface
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getServerParams()
|
||||
public function getServerParams(): array
|
||||
{
|
||||
// TODO: Implement getServerParams() method.
|
||||
return $this->server;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -31,9 +44,10 @@ class ServerRequest extends Request implements ServerRequestInterface
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getCookieParams()
|
||||
public function getCookieParams(): array
|
||||
{
|
||||
// TODO: Implement getCookieParams() method.
|
||||
return $this->cookies;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,9 +67,11 @@ class ServerRequest extends Request implements ServerRequestInterface
|
||||
* @param array $cookies Array of key/value pairs representing cookies.
|
||||
* @return static
|
||||
*/
|
||||
public function withCookieParams(array $cookies)
|
||||
public function withCookieParams(array $cookies): static
|
||||
{
|
||||
// TODO: Implement withCookieParams() method.
|
||||
$this->cookies = $cookies;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -70,9 +86,10 @@ class ServerRequest extends Request implements ServerRequestInterface
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getQueryParams()
|
||||
public function getQueryParams(): array
|
||||
{
|
||||
// TODO: Implement getQueryParams() method.
|
||||
return $this->query;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,9 +114,11 @@ class ServerRequest extends Request implements ServerRequestInterface
|
||||
* $_GET.
|
||||
* @return static
|
||||
*/
|
||||
public function withQueryParams(array $query)
|
||||
public function withQueryParams(array $query): static
|
||||
{
|
||||
// TODO: Implement withQueryParams() method.
|
||||
$this->query = $query;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -114,9 +133,10 @@ class ServerRequest extends Request implements ServerRequestInterface
|
||||
* @return array An array tree of UploadedFileInterface instances; an empty
|
||||
* array MUST be returned if no data is present.
|
||||
*/
|
||||
public function getUploadedFiles()
|
||||
public function getUploadedFiles(): array
|
||||
{
|
||||
// TODO: Implement getUploadedFiles() method.
|
||||
return $this->files;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -130,9 +150,11 @@ class ServerRequest extends Request implements ServerRequestInterface
|
||||
* @return static
|
||||
* @throws \InvalidArgumentException if an invalid structure is provided.
|
||||
*/
|
||||
public function withUploadedFiles(array $uploadedFiles)
|
||||
public function withUploadedFiles(array $uploadedFiles): static
|
||||
{
|
||||
// TODO: Implement withUploadedFiles() method.
|
||||
$this->files = $uploadedFiles;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -150,9 +172,10 @@ class ServerRequest extends Request implements ServerRequestInterface
|
||||
* @return null|array|object The deserialized body parameters, if any.
|
||||
* These will typically be an array or object.
|
||||
*/
|
||||
public function getParsedBody()
|
||||
public function getParsedBody(): object|array|null
|
||||
{
|
||||
// TODO: Implement getParsedBody() method.
|
||||
return $this->posts;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -183,9 +206,11 @@ class ServerRequest extends Request implements ServerRequestInterface
|
||||
* @throws \InvalidArgumentException if an unsupported argument type is
|
||||
* provided.
|
||||
*/
|
||||
public function withParsedBody($data)
|
||||
public function withParsedBody($data): static
|
||||
{
|
||||
// TODO: Implement withParsedBody() method.
|
||||
$this->posts = $data;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -199,27 +224,31 @@ class ServerRequest extends Request implements ServerRequestInterface
|
||||
*
|
||||
* @return array Attributes derived from the request.
|
||||
*/
|
||||
public function getAttributes()
|
||||
public function getAttributes(): array
|
||||
{
|
||||
// TODO: Implement getAttributes() method.
|
||||
}/**
|
||||
* Retrieve a single derived request attribute.
|
||||
*
|
||||
* Retrieves a single derived request attribute as described in
|
||||
* getAttributes(). If the attribute has not been previously set, returns
|
||||
* the default value as provided.
|
||||
*
|
||||
* This method obviates the need for a hasAttribute() method, as it allows
|
||||
* specifying a default value to return if the attribute is not found.
|
||||
*
|
||||
* @param string $name The attribute name.
|
||||
* @param mixed $default Default value to return if the attribute does not exist.
|
||||
* @return mixed
|
||||
* @see getAttributes()
|
||||
*/
|
||||
public function getAttribute(string $name, $default = null)
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a single derived request attribute.
|
||||
*
|
||||
* Retrieves a single derived request attribute as described in
|
||||
* getAttributes(). If the attribute has not been previously set, returns
|
||||
* the default value as provided.
|
||||
*
|
||||
* This method obviates the need for a hasAttribute() method, as it allows
|
||||
* specifying a default value to return if the attribute is not found.
|
||||
*
|
||||
* @param string $name The attribute name.
|
||||
* @param mixed $default Default value to return if the attribute does not exist.
|
||||
* @return mixed
|
||||
* @see getAttributes()
|
||||
*/
|
||||
public function getAttribute(string $name, $default = null): mixed
|
||||
{
|
||||
// TODO: Implement getAttribute() method.
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -237,9 +266,10 @@ class ServerRequest extends Request implements ServerRequestInterface
|
||||
* @return static
|
||||
* @see getAttributes()
|
||||
*/
|
||||
public function withAttribute(string $name, $value)
|
||||
public function withAttribute(string $name, $value): static
|
||||
{
|
||||
// TODO: Implement withAttribute() method.
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -256,8 +286,9 @@ class ServerRequest extends Request implements ServerRequestInterface
|
||||
* @return static
|
||||
* @see getAttributes()
|
||||
*/
|
||||
public function withoutAttribute(string $name)
|
||||
public function withoutAttribute(string $name): static
|
||||
{
|
||||
// TODO: Implement withoutAttribute() method.
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
+86
-25
@@ -1,12 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Router\Message;
|
||||
namespace Kiri\Router\Constrict;
|
||||
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
|
||||
class Stream implements StreamInterface
|
||||
{
|
||||
|
||||
public string $content = '';
|
||||
|
||||
|
||||
public int $size = 0;
|
||||
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
*/
|
||||
public function __construct(string $content = '')
|
||||
{
|
||||
$this->content = $content;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reads all data from the stream into a string, from the beginning to end.
|
||||
*
|
||||
@@ -24,6 +39,7 @@ class Stream implements StreamInterface
|
||||
public function __toString()
|
||||
{
|
||||
// TODO: Implement __toString() method.
|
||||
return $this->content;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -31,9 +47,14 @@ class Stream implements StreamInterface
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function close()
|
||||
public function close(): void
|
||||
{
|
||||
// TODO: Implement close() method.
|
||||
if (is_resource($this->content)) {
|
||||
fclose($this->content);
|
||||
} else {
|
||||
$this->content = '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -43,9 +64,10 @@ class Stream implements StreamInterface
|
||||
*
|
||||
* @return resource|null Underlying PHP stream, if any
|
||||
*/
|
||||
public function detach()
|
||||
public function detach(): mixed
|
||||
{
|
||||
// TODO: Implement detach() method.
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,9 +75,10 @@ class Stream implements StreamInterface
|
||||
*
|
||||
* @return int|null Returns the size in bytes if known, or null if unknown.
|
||||
*/
|
||||
public function getSize()
|
||||
public function getSize(): ?int
|
||||
{
|
||||
// TODO: Implement getSize() method.
|
||||
return $this->size;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -64,9 +87,10 @@ class Stream implements StreamInterface
|
||||
* @return int Position of the file pointer
|
||||
* @throws \RuntimeException on error.
|
||||
*/
|
||||
public function tell()
|
||||
public function tell(): int
|
||||
{
|
||||
// TODO: Implement tell() method.
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,9 +98,10 @@ class Stream implements StreamInterface
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function eof()
|
||||
public function eof(): bool
|
||||
{
|
||||
// TODO: Implement eof() method.
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -84,9 +109,10 @@ class Stream implements StreamInterface
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isSeekable()
|
||||
public function isSeekable(): bool
|
||||
{
|
||||
// TODO: Implement isSeekable() method.
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -101,22 +127,28 @@ class Stream implements StreamInterface
|
||||
* SEEK_END: Set position to end-of-stream plus offset.
|
||||
* @throws \RuntimeException on failure.
|
||||
*/
|
||||
public function seek(int $offset, int $whence = SEEK_SET)
|
||||
public function seek(int $offset, int $whence = SEEK_SET): void
|
||||
{
|
||||
// TODO: Implement seek() method.
|
||||
}/**
|
||||
* Seek to the beginning of the stream.
|
||||
*
|
||||
* If the stream is not seekable, this method will raise an exception;
|
||||
* otherwise, it will perform a seek(0).
|
||||
*
|
||||
* @throws \RuntimeException on failure.
|
||||
* @link http://www.php.net/manual/en/function.fseek.php
|
||||
* @see seek()
|
||||
*/
|
||||
public function rewind()
|
||||
if (is_resource($this->content)) {
|
||||
fseek($this->content, $offset, $whence);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Seek to the beginning of the stream.
|
||||
*
|
||||
* If the stream is not seekable, this method will raise an exception;
|
||||
* otherwise, it will perform a seek(0).
|
||||
*
|
||||
* @throws \RuntimeException on failure.
|
||||
* @link http://www.php.net/manual/en/function.fseek.php
|
||||
* @see seek()
|
||||
*/
|
||||
public function rewind(): void
|
||||
{
|
||||
// TODO: Implement rewind() method.
|
||||
$this->seek(0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -124,9 +156,13 @@ class Stream implements StreamInterface
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isWritable()
|
||||
public function isWritable(): bool
|
||||
{
|
||||
// TODO: Implement isWritable() method.
|
||||
if (is_resource($this->content)) {
|
||||
return is_writable($this->content);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -136,9 +172,17 @@ class Stream implements StreamInterface
|
||||
* @return int Returns the number of bytes written to the stream.
|
||||
* @throws \RuntimeException on failure.
|
||||
*/
|
||||
public function write(string $string)
|
||||
public function write(string $string): int
|
||||
{
|
||||
// TODO: Implement write() method.
|
||||
if (is_resource($this->content)) {
|
||||
$this->content = fopen($string, 'wr');
|
||||
$this->size = filesize($string);
|
||||
} else {
|
||||
$this->content = $string;
|
||||
$this->size = mb_strlen($string);
|
||||
}
|
||||
return $this->size;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,9 +190,13 @@ class Stream implements StreamInterface
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isReadable()
|
||||
public function isReadable(): bool
|
||||
{
|
||||
// TODO: Implement isReadable() method.
|
||||
if (is_resource($this->content)) {
|
||||
return is_readable($this->content);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -161,9 +209,14 @@ class Stream implements StreamInterface
|
||||
* if no bytes are available.
|
||||
* @throws \RuntimeException if an error occurs.
|
||||
*/
|
||||
public function read(int $length)
|
||||
public function read(int $length): string
|
||||
{
|
||||
// TODO: Implement read() method.
|
||||
if (!is_resource($this->content)) {
|
||||
return mb_substr($this->content, 0, $length);
|
||||
} else {
|
||||
return fread($this->content, $length);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -173,9 +226,13 @@ class Stream implements StreamInterface
|
||||
* @throws \RuntimeException if unable to read or an error occurs while
|
||||
* reading.
|
||||
*/
|
||||
public function getContents()
|
||||
public function getContents(): string
|
||||
{
|
||||
// TODO: Implement getContents() method.
|
||||
if (is_resource($this->content)) {
|
||||
return fread($this->content, $this->getSize());
|
||||
}
|
||||
return $this->content;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -190,8 +247,12 @@ class Stream implements StreamInterface
|
||||
* provided. Returns a specific key value if a key is provided and the
|
||||
* value is found, or null if the key is not found.
|
||||
*/
|
||||
public function getMetadata(?string $key = null)
|
||||
public function getMetadata(?string $key = null): mixed
|
||||
{
|
||||
// TODO: Implement getMetadata() method.
|
||||
if (is_resource($this->content)) {
|
||||
return stream_get_meta_data($this->content);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
+69
-16
@@ -1,12 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Router\Message;
|
||||
namespace Kiri\Router\Constrict;
|
||||
|
||||
use Psr\Http\Message\UriInterface;
|
||||
|
||||
class Uri implements UriInterface
|
||||
{
|
||||
|
||||
private string $scheme = '';
|
||||
private string $host = '';
|
||||
private int $port = 80;
|
||||
private string $path = '';
|
||||
private string $user = '';
|
||||
private string $password = '';
|
||||
private string $queryString;
|
||||
private string $fragment;
|
||||
|
||||
/**
|
||||
* Retrieve the scheme component of the URI.
|
||||
*
|
||||
@@ -21,9 +30,10 @@ class Uri implements UriInterface
|
||||
* @see https://tools.ietf.org/html/rfc3986#section-3.1
|
||||
* @return string The URI scheme.
|
||||
*/
|
||||
public function getScheme()
|
||||
public function getScheme(): string
|
||||
{
|
||||
// TODO: Implement getScheme() method.
|
||||
return $this->scheme;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -44,9 +54,10 @@ class Uri implements UriInterface
|
||||
* @see https://tools.ietf.org/html/rfc3986#section-3.2
|
||||
* @return string The URI authority, in "[user-info@]host[:port]" format.
|
||||
*/
|
||||
public function getAuthority()
|
||||
public function getAuthority(): string
|
||||
{
|
||||
// TODO: Implement getAuthority() method.
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -64,9 +75,10 @@ class Uri implements UriInterface
|
||||
*
|
||||
* @return string The URI user information, in "username[:password]" format.
|
||||
*/
|
||||
public function getUserInfo()
|
||||
public function getUserInfo(): string
|
||||
{
|
||||
// TODO: Implement getUserInfo() method.
|
||||
return $this->user . '[' . $this->password . ']';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -80,9 +92,10 @@ class Uri implements UriInterface
|
||||
* @see http://tools.ietf.org/html/rfc3986#section-3.2.2
|
||||
* @return string The URI host.
|
||||
*/
|
||||
public function getHost()
|
||||
public function getHost(): string
|
||||
{
|
||||
// TODO: Implement getHost() method.
|
||||
return $this->host;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -100,9 +113,10 @@ class Uri implements UriInterface
|
||||
*
|
||||
* @return null|int The URI port.
|
||||
*/
|
||||
public function getPort()
|
||||
public function getPort(): ?int
|
||||
{
|
||||
// TODO: Implement getPort() method.
|
||||
return $this->port;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -130,9 +144,10 @@ class Uri implements UriInterface
|
||||
* @see https://tools.ietf.org/html/rfc3986#section-3.3
|
||||
* @return string The URI path.
|
||||
*/
|
||||
public function getPath()
|
||||
public function getPath(): string
|
||||
{
|
||||
// TODO: Implement getPath() method.
|
||||
return $this->path;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -155,9 +170,10 @@ class Uri implements UriInterface
|
||||
* @see https://tools.ietf.org/html/rfc3986#section-3.4
|
||||
* @return string The URI query string.
|
||||
*/
|
||||
public function getQuery()
|
||||
public function getQuery(): string
|
||||
{
|
||||
// TODO: Implement getQuery() method.
|
||||
return $this->queryString;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -176,9 +192,10 @@ class Uri implements UriInterface
|
||||
* @see https://tools.ietf.org/html/rfc3986#section-3.5
|
||||
* @return string The URI fragment.
|
||||
*/
|
||||
public function getFragment()
|
||||
public function getFragment(): string
|
||||
{
|
||||
// TODO: Implement getFragment() method.
|
||||
return $this->fragment;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -196,9 +213,11 @@ class Uri implements UriInterface
|
||||
* @return static A new instance with the specified scheme.
|
||||
* @throws \InvalidArgumentException for invalid or unsupported schemes.
|
||||
*/
|
||||
public function withScheme(string $scheme)
|
||||
public function withScheme(string $scheme): static
|
||||
{
|
||||
// TODO: Implement withScheme() method.
|
||||
$this->scheme = $scheme;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -215,9 +234,12 @@ class Uri implements UriInterface
|
||||
* @param null|string $password The password associated with $user.
|
||||
* @return static A new instance with the specified user information.
|
||||
*/
|
||||
public function withUserInfo(string $user, ?string $password = null)
|
||||
public function withUserInfo(string $user, ?string $password = null): static
|
||||
{
|
||||
// TODO: Implement withUserInfo() method.
|
||||
$this->user = $user;
|
||||
$this->password = $password;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -232,9 +254,11 @@ class Uri implements UriInterface
|
||||
* @return static A new instance with the specified host.
|
||||
* @throws \InvalidArgumentException for invalid hostnames.
|
||||
*/
|
||||
public function withHost(string $host)
|
||||
public function withHost(string $host): static
|
||||
{
|
||||
// TODO: Implement withHost() method.
|
||||
$this->host = $host;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -254,9 +278,11 @@ class Uri implements UriInterface
|
||||
* @return static A new instance with the specified port.
|
||||
* @throws \InvalidArgumentException for invalid ports.
|
||||
*/
|
||||
public function withPort(?int $port)
|
||||
public function withPort(?int $port): static
|
||||
{
|
||||
// TODO: Implement withPort() method.
|
||||
$this->port = $port;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -281,9 +307,11 @@ class Uri implements UriInterface
|
||||
* @return static A new instance with the specified path.
|
||||
* @throws \InvalidArgumentException for invalid paths.
|
||||
*/
|
||||
public function withPath(string $path)
|
||||
public function withPath(string $path): static
|
||||
{
|
||||
// TODO: Implement withPath() method.
|
||||
$this->path = $path;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -301,9 +329,11 @@ class Uri implements UriInterface
|
||||
* @return static A new instance with the specified query string.
|
||||
* @throws \InvalidArgumentException for invalid query strings.
|
||||
*/
|
||||
public function withQuery(string $query)
|
||||
public function withQuery(string $query): static
|
||||
{
|
||||
// TODO: Implement withQuery() method.
|
||||
$this->queryString = $query;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -320,9 +350,11 @@ class Uri implements UriInterface
|
||||
* @param string $fragment The fragment to use with the new instance.
|
||||
* @return static A new instance with the specified fragment.
|
||||
*/
|
||||
public function withFragment(string $fragment)
|
||||
public function withFragment(string $fragment): static
|
||||
{
|
||||
// TODO: Implement withFragment() method.
|
||||
$this->fragment = $fragment;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -351,5 +383,26 @@ class Uri implements UriInterface
|
||||
public function __toString()
|
||||
{
|
||||
// TODO: Implement __toString() method.
|
||||
return $this->scheme . '://x.x.x.x:' . $this->port . '/' . $this->path . '?' . $this->queryString;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param \Swoole\Http\Request $request
|
||||
* @return UriInterface
|
||||
*/
|
||||
public static function parse(\Swoole\Http\Request $request): UriInterface
|
||||
{
|
||||
$uri = new static();
|
||||
$uri->queryString = $request->server['query_string'];
|
||||
$uri->path = $request->server['path_info'];
|
||||
$uri->port = $request->server['server_port'];
|
||||
if (isset($request->server['https']) && $request->server['https'] !== 'off') {
|
||||
$uri->scheme = 'https';
|
||||
} else {
|
||||
$uri->scheme = 'http';
|
||||
}
|
||||
return $uri;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Message;
|
||||
namespace Kiri\Router;
|
||||
|
||||
|
||||
enum ContentType
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Router\Inject;
|
||||
namespace Kiri\Router;
|
||||
|
||||
use Closure;
|
||||
use ReflectionClass;
|
||||
use ReflectionException;
|
||||
use ReflectionMethod;
|
||||
@@ -11,19 +12,31 @@ class ControllerInterpreter
|
||||
|
||||
|
||||
/**
|
||||
* @param string $className
|
||||
* @param object $class
|
||||
* @param string|ReflectionMethod $method
|
||||
* @param ReflectionClass|null $reflection
|
||||
* @return void
|
||||
* @return Handler
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
public function addRouteByString(string $className, string|ReflectionMethod $method, ?ReflectionClass $reflection = null): void
|
||||
public function addRouteByString(object $class, string|ReflectionMethod $method, ?ReflectionClass $reflection = null): Handler
|
||||
{
|
||||
$class = \Kiri::getDi()->get($className);
|
||||
if (is_null($reflection)) {
|
||||
$reflection = \Kiri::getDi()->getReflect($className);
|
||||
$reflection = \Kiri::getDi()->getReflectionClass($class::class);
|
||||
}
|
||||
$this->resolveMethod($class, $method, $reflection);
|
||||
return $this->resolveMethod($method, $reflection);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Closure $method
|
||||
* @return Handler
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
public function addRouteByClosure(Closure $method): Handler
|
||||
{
|
||||
$reflection = \Kiri::getDi()->getFunctionParams($method);
|
||||
|
||||
return new Handler($method, $reflection);
|
||||
}
|
||||
|
||||
|
||||
@@ -31,96 +44,34 @@ class ControllerInterpreter
|
||||
* @param object $class
|
||||
* @param string|ReflectionMethod $method
|
||||
* @param ReflectionClass|null $reflection
|
||||
* @return void
|
||||
* @return Handler
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
public function addRouteByObject(object $class, string|ReflectionMethod $method, ?ReflectionClass $reflection = null): void
|
||||
public function addRouteByObject(object $class, string|ReflectionMethod $method, ?ReflectionClass $reflection = null): Handler
|
||||
{
|
||||
if (is_null($reflection)) {
|
||||
$reflection = \Kiri::getDi()->getReflect($class::class);
|
||||
$reflection = \Kiri::getDi()->getReflectionClass($class::class);
|
||||
}
|
||||
$this->resolveMethod($class, $method, $reflection);
|
||||
return $this->resolveMethod($method, $reflection);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param object $class
|
||||
* @param string|ReflectionMethod $reflectionMethod
|
||||
* @param ReflectionClass $reflectionClass
|
||||
* @return void
|
||||
* @return Handler
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
public function resolveMethod(object $class, string|\ReflectionMethod $reflectionMethod, ReflectionClass $reflectionClass): void
|
||||
public function resolveMethod(string|\ReflectionMethod $reflectionMethod, ReflectionClass $reflectionClass): Handler
|
||||
{
|
||||
if (is_string($reflectionMethod)) {
|
||||
$reflectionMethod = $reflectionClass->getMethod($reflectionMethod);
|
||||
}
|
||||
|
||||
$this->resolveProperties($reflectionClass, $class);
|
||||
$container = \Kiri::getDi();
|
||||
$parameters = $container->getMethodParams($reflectionMethod);
|
||||
|
||||
$parameters = $this->resolveMethodParams($reflectionMethod->getParameters());
|
||||
|
||||
$handler = new Handler([$reflectionClass->getName(), $reflectionMethod->getName()], $parameters);
|
||||
|
||||
ActionManager::add($reflectionClass->getName(), $reflectionMethod->getName(), $handler);
|
||||
return new Handler([$reflectionClass->getName(), $reflectionMethod->getName()], $parameters);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param ReflectionClass $reflectionClass
|
||||
* @param object $class
|
||||
* @return void
|
||||
*/
|
||||
public function resolveProperties(ReflectionClass $reflectionClass, object $class): void
|
||||
{
|
||||
$properties = $reflectionClass->getProperties();
|
||||
foreach ($properties as $property) {
|
||||
$propertyAttributes = $property->getAttributes();
|
||||
|
||||
foreach ($propertyAttributes as $attribute) {
|
||||
$attribute->newInstance()->dispatch($class, $property->getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $parameters
|
||||
* @return array
|
||||
*/
|
||||
public function resolveMethodParams(array $parameters): array
|
||||
{
|
||||
$params = [];
|
||||
foreach ($parameters as $parameter) {
|
||||
$parameterAttributes = $parameter->getAttributes();
|
||||
if (count($parameterAttributes) < 1) {
|
||||
if ($parameter->isDefaultValueAvailable()) {
|
||||
$value = $parameter->getDefaultValue();
|
||||
} else if ($parameter->getType() === null) {
|
||||
$value = $parameter->getType();
|
||||
} else {
|
||||
$value = $parameter->getType()->getName();
|
||||
if (class_exists($value) || interface_exists($value)) {
|
||||
$value = \Kiri::getDi()->get($value);
|
||||
} else {
|
||||
$value = match ($parameter->getType()) {
|
||||
'string' => '',
|
||||
'int', 'float' => 0,
|
||||
'', null, 'object', 'mixed' => NULL,
|
||||
'bool' => false,
|
||||
'default' => null
|
||||
};
|
||||
}
|
||||
}
|
||||
$params[$parameter->getName()] = $value;
|
||||
} else {
|
||||
$attribute = $parameterAttributes[0]->newInstance();
|
||||
|
||||
$params[$parameter->getName()] = $attribute->dispatch();
|
||||
}
|
||||
}
|
||||
return $params;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+4
-2
@@ -1,8 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Message\Handler;
|
||||
namespace Kiri\Router;
|
||||
|
||||
use Kiri;
|
||||
use ReflectionException;
|
||||
|
||||
class DataGrip
|
||||
{
|
||||
@@ -13,11 +14,12 @@ class DataGrip
|
||||
/**
|
||||
* @param $type
|
||||
* @return RouterCollector
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
public function get($type): RouterCollector
|
||||
{
|
||||
if (!isset($this->servers[$type])) {
|
||||
$this->servers[$type] = Kiri::getDi()->create(RouterCollector::class);
|
||||
$this->servers[$type] = Kiri::getDi()->make(RouterCollector::class);
|
||||
}
|
||||
return $this->servers[$type];
|
||||
}
|
||||
|
||||
+33
-1
@@ -2,7 +2,39 @@
|
||||
|
||||
namespace Kiri\Router;
|
||||
|
||||
class Handler
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
use ReflectionException;
|
||||
|
||||
class Handler implements RequestHandlerInterface
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param array|\Closure $handler
|
||||
* @param array $parameter
|
||||
*/
|
||||
public function __construct(public array|\Closure $handler, public array $parameter)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param ServerRequestInterface $request
|
||||
* @return ResponseInterface
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||
{
|
||||
// TODO: Implement handle() method.
|
||||
$result = call_user_func($this->handler, ...$this->parameter);
|
||||
if ($result instanceof ResponseInterface) {
|
||||
return $result;
|
||||
} else {
|
||||
$response = \Kiri::getDi()->get(ResponseInterface::class);
|
||||
return $response->rewrite();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,7 +2,26 @@
|
||||
|
||||
namespace Kiri\Router;
|
||||
|
||||
class HttpRequestHandler
|
||||
use Kiri\Router\Base\AbstractHandler;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
use ReflectionException;
|
||||
|
||||
class HttpRequestHandler extends AbstractHandler implements RequestHandlerInterface
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param ServerRequestInterface $request
|
||||
* @return ResponseInterface
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
public function handle(ServerRequestInterface $request): ResponseInterface
|
||||
{
|
||||
// TODO: Implement handle() method.
|
||||
return $this->execute($request);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -2,7 +2,52 @@
|
||||
|
||||
namespace Kiri\Router;
|
||||
|
||||
class HttpResponseEmitter
|
||||
use Exception;
|
||||
use Kiri\Di\Interface\ResponseEmitter;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
|
||||
class HttpResponseEmitter implements ResponseEmitter
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param Response $proxy
|
||||
* @param object $response
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function sender(ResponseInterface $proxy, object $response): void
|
||||
{
|
||||
// TODO: Implement sender() method.
|
||||
$this->writeParams($proxy, $response);
|
||||
|
||||
$proxy->write($response);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Response $proxy
|
||||
* @param object $response
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
private function writeParams(ResponseInterface $proxy, object $response): void
|
||||
{
|
||||
$response->setStatusCode($proxy->getStatusCode());
|
||||
/** @var ServerRequest $request */
|
||||
$request = \Kiri::service()->get('request');
|
||||
foreach ($request->getHeaders() as $name => $header) {
|
||||
$response->header($name, implode(', ', $header));
|
||||
}
|
||||
|
||||
$response->setStatusCode($proxy->getStatusCode());
|
||||
foreach ($request->getCookieParams() as $cookie) {
|
||||
$response->setCookie(...$cookie);
|
||||
}
|
||||
$response->header('Server', 'swoole');
|
||||
$response->header('Swoole-Version', swoole_version());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,8 +1,69 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Inject\Route;
|
||||
namespace Kiri\Router\Inject;
|
||||
|
||||
use Kiri\Router\Base\Middleware as MiddlewareManager;
|
||||
use Kiri\Router\Interface\ValidatorInterface;
|
||||
use Kiri\Router\Validator\Validator;
|
||||
use Kiri\Router\Validator\ValidatorMiddleware;
|
||||
use ReflectionException;
|
||||
|
||||
abstract class AbstractRequestMethod
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param string $formValidate
|
||||
*/
|
||||
public function __construct(readonly public string $path, public string $formValidate = '')
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param object $class
|
||||
* @param string $method
|
||||
* @return void
|
||||
* @throws ReflectionException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function registerMiddleware(object $class, string $method): void
|
||||
{
|
||||
$reflectionMethod = \Kiri::getDi()->getMethod($class::class, $method);
|
||||
$middleware = $reflectionMethod->getAttributes(Middleware::class);
|
||||
|
||||
$middlewareManager = \Kiri::getDi()->get(MiddlewareManager::class);
|
||||
foreach ($middleware as $value) {
|
||||
/** @var Middleware $instance */
|
||||
$instance = $value->newInstance();
|
||||
|
||||
$middlewareManager->addPathMiddleware($this->path, $instance->middleware);
|
||||
}
|
||||
|
||||
if ($this->formValidate !== '') {
|
||||
$middlewareManager->addPathMiddleware($this->path, new ValidatorMiddleware($this->getFormRule()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Validator|null
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
public function getFormRule(): ?Validator
|
||||
{
|
||||
$validator = new Validator();
|
||||
$reflect = \Kiri::getDi()->getReflectionClass($this->formValidate);
|
||||
$model = $reflect->newInstanceWithoutConstructor();
|
||||
foreach ($reflect->getProperties() as $property) {
|
||||
foreach ($property->getAttributes() as $attribute) {
|
||||
$rule = $attribute->newInstance();
|
||||
if ($rule instanceof ValidatorInterface) {
|
||||
$validator->addRule($property->getName(), $model, $rule);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $validator;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,16 @@
|
||||
|
||||
namespace Kiri\Router\Inject;
|
||||
|
||||
#[\Attribute(\Attribute::TARGET_METHOD)]
|
||||
class Aspect
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param string $aspect
|
||||
*/
|
||||
public function __construct(readonly public string $aspect)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,49 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Inject\Route;
|
||||
namespace Kiri\Router\Inject;
|
||||
|
||||
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use ReflectionException;
|
||||
|
||||
#[\Attribute(\Attribute::TARGET_CLASS)]
|
||||
class Controller
|
||||
{
|
||||
|
||||
|
||||
readonly public ?RequestInterface $request;
|
||||
|
||||
|
||||
|
||||
readonly public ResponseInterface $response;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->request = \Kiri::getDi()->get(RequestInterface::class);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param object $class
|
||||
* @return void
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
public function dispatch(object $class): void
|
||||
{
|
||||
// TODO: Implement dispatch() method.
|
||||
$reflectionClass = \Kiri::getDi()->getReflect($class::class);
|
||||
|
||||
$scheduler = \Kiri::getDi()->get(ControllerInterpreter::class);
|
||||
|
||||
foreach ($reflectionClass->getMethods() as $reflectionMethod) {
|
||||
$scheduler->addRouteByObject($class, $reflectionMethod, $reflectionClass);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+10
-10
@@ -1,33 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Inject\Route;
|
||||
namespace Kiri\Router\Inject;
|
||||
|
||||
use Exception;
|
||||
use Kiri\Annotation\Route\RequestMethod;
|
||||
use Kiri\Message\Handler\Router;
|
||||
use Kiri\Router\InjectRouteInterface;
|
||||
use Kiri\Router\Router;
|
||||
use ReflectionException;
|
||||
|
||||
#[\Attribute(\Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
|
||||
class Delete extends AbstractRequestMethod implements InjectRouteInterface
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param array $params
|
||||
*/
|
||||
public function __construct(public string $path, public array $params = [])
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param object $class
|
||||
* @param string $method
|
||||
* @return void
|
||||
* @throws ReflectionException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function dispatch(object $class, string $method): void
|
||||
{
|
||||
// TODO: Implement dispatch() method.
|
||||
Router::addRoute(RequestMethod::REQUEST_DELETE, $this->path, [$class, $method]);
|
||||
|
||||
$this->registerMiddleware($class, $method);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Inject\Route;
|
||||
namespace Kiri\Router\Inject;
|
||||
|
||||
|
||||
#[\Attribute(\Attribute::TARGET_METHOD)]
|
||||
|
||||
+10
-11
@@ -1,33 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Inject\Route;
|
||||
namespace Kiri\Router\Inject;
|
||||
|
||||
use Exception;
|
||||
use Kiri\Annotation\Route\RequestMethod;
|
||||
use Kiri\Message\Handler\Router;
|
||||
use Kiri\Router\InjectRouteInterface;
|
||||
use Kiri\Router\Router;
|
||||
use ReflectionException;
|
||||
|
||||
#[\Attribute(\Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
|
||||
class Get extends AbstractRequestMethod implements InjectRouteInterface
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param array $params
|
||||
*/
|
||||
public function __construct(public string $path, public array $params = [])
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param object $class
|
||||
* @param string $method
|
||||
* @return void
|
||||
* @throws ReflectionException
|
||||
* @throws Exception
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
public function dispatch(object $class, string $method): void
|
||||
{
|
||||
// TODO: Implement dispatch() method.
|
||||
Router::addRoute(RequestMethod::REQUEST_GET, $this->path, [$class, $method]);
|
||||
|
||||
$this->registerMiddleware($class, $method);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+8
-10
@@ -1,28 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Inject\Route;
|
||||
namespace Kiri\Router\Inject;
|
||||
|
||||
use Exception;
|
||||
use Kiri\Annotation\Route\RequestMethod;
|
||||
use Kiri\Message\Handler\Router;
|
||||
use Kiri\Router\InjectRouteInterface;
|
||||
use Kiri\Router\Router;
|
||||
use ReflectionException;
|
||||
|
||||
#[\Attribute(\Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
|
||||
class Head extends AbstractRequestMethod implements InjectRouteInterface
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param array $params
|
||||
*/
|
||||
public function __construct(public string $path, public array $params = [])
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param object $class
|
||||
* @param string $method
|
||||
* @return void
|
||||
* @throws ReflectionException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function dispatch(object $class, string $method): void
|
||||
{
|
||||
@@ -30,4 +27,5 @@ class Head extends AbstractRequestMethod implements InjectRouteInterface
|
||||
Router::addRoute(RequestMethod::REQUEST_HEAD, $this->path, [$class, $method]);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Inject\Route;
|
||||
namespace Kiri\Router\Inject;
|
||||
|
||||
|
||||
#[\Attribute(\Attribute::TARGET_METHOD)]
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Inject\Route;
|
||||
namespace Kiri\Router\Inject;
|
||||
|
||||
use Kiri\Inject\InjectPropertyInterface;
|
||||
use Kiri\Message\Handler\Abstracts\MiddlewareManager;
|
||||
use Kiri\Di\Interface\InjectPropertyInterface;
|
||||
|
||||
#[\Attribute(\Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
|
||||
class Middleware implements InjectPropertyInterface
|
||||
@@ -24,8 +23,6 @@ class Middleware implements InjectPropertyInterface
|
||||
*/
|
||||
public function dispatch(object $class, string $property): void
|
||||
{
|
||||
// TODO: Implement dispatch() method.
|
||||
MiddlewareManager::add($class::class, $property, $this->middleware);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+10
-9
@@ -1,33 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Inject\Route;
|
||||
namespace Kiri\Router\Inject;
|
||||
|
||||
use Exception;
|
||||
use Kiri\Annotation\Route\RequestMethod;
|
||||
use Kiri\Message\Handler\Router;
|
||||
use Kiri\Router\InjectRouteInterface;
|
||||
use Kiri\Router\Router;
|
||||
use ReflectionException;
|
||||
|
||||
#[\Attribute(\Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
|
||||
class Options extends AbstractRequestMethod implements InjectRouteInterface
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param array $params
|
||||
*/
|
||||
public function __construct(public string $path, public array $params = [])
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param object $class
|
||||
* @param string $method
|
||||
* @return void
|
||||
* @throws ReflectionException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function dispatch(object $class, string $method): void
|
||||
{
|
||||
// TODO: Implement dispatch() method.
|
||||
Router::addRoute(RequestMethod::REQUEST_OPTIONS, $this->path, [$class, $method]);
|
||||
|
||||
$this->registerMiddleware($class, $method);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+35
-1
@@ -2,7 +2,41 @@
|
||||
|
||||
namespace Kiri\Router\Inject;
|
||||
|
||||
class Other
|
||||
use Exception;
|
||||
use Kiri\Router\InjectRouteInterface;
|
||||
use Kiri\Router\Router;
|
||||
use ReflectionException;
|
||||
|
||||
#[\Attribute(\Attribute::TARGET_METHOD)]
|
||||
class Other extends AbstractRequestMethod implements InjectRouteInterface
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param string $method
|
||||
* @param string $path
|
||||
* @param string $formValidate
|
||||
*/
|
||||
public function __construct(readonly public string $method, string $path, string $formValidate = '')
|
||||
{
|
||||
parent::__construct($path, $formValidate);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param object $class
|
||||
* @param string $method
|
||||
* @return void
|
||||
* @throws ReflectionException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function dispatch(object $class, string $method): void
|
||||
{
|
||||
// TODO: Implement dispatch() method.
|
||||
Router::addRoute([$this->method], $this->path, [$class, $method]);
|
||||
|
||||
$this->registerMiddleware($class, $method);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+10
-10
@@ -1,33 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Inject\Route;
|
||||
namespace Kiri\Router\Inject;
|
||||
|
||||
use Exception;
|
||||
use Kiri\Annotation\Route\RequestMethod;
|
||||
use Kiri\Message\Handler\Router;
|
||||
use Kiri\Router\InjectRouteInterface;
|
||||
use Kiri\Router\Router;
|
||||
use ReflectionException;
|
||||
|
||||
#[\Attribute(\Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
|
||||
class Post extends AbstractRequestMethod implements InjectRouteInterface
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param array $params
|
||||
*/
|
||||
public function __construct(public string $path, public array $params = [])
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param object $class
|
||||
* @param string $method
|
||||
* @return void
|
||||
* @throws ReflectionException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function dispatch(object $class, string $method): void
|
||||
{
|
||||
// TODO: Implement dispatch() method.
|
||||
Router::addRoute(RequestMethod::REQUEST_POST, $this->path, [$class, $method]);
|
||||
|
||||
$this->registerMiddleware($class, $method);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+10
-11
@@ -1,33 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Inject\Route;
|
||||
namespace Kiri\Router\Inject;
|
||||
|
||||
use Exception;
|
||||
use Kiri\Annotation\Route\RequestMethod;
|
||||
use Kiri\Message\Handler\Router;
|
||||
use Kiri\Router\InjectRouteInterface;
|
||||
use Kiri\Router\Router;
|
||||
use Kiri\Router\Base\Middleware as MiddlewareManager;
|
||||
use ReflectionException;
|
||||
|
||||
#[\Attribute(\Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
|
||||
class Put extends AbstractRequestMethod implements InjectRouteInterface
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param array $params
|
||||
*/
|
||||
public function __construct(public string $path, public array $params = [])
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param object $class
|
||||
* @param string $method
|
||||
* @return void
|
||||
* @throws ReflectionException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function dispatch(object $class, string $method): void
|
||||
{
|
||||
// TODO: Implement dispatch() method.
|
||||
Router::addRoute(RequestMethod::REQUEST_PUT, $this->path, [$class, $method]);
|
||||
|
||||
$this->registerMiddleware($class, $method);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Inject\Route;
|
||||
namespace Kiri\Router\Inject;
|
||||
|
||||
|
||||
#[\Attribute(\Attribute::TARGET_PARAMETER)]
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Message\Abstracts;
|
||||
namespace Kiri\Router\Interface;
|
||||
|
||||
use Kiri\Message\Constrict\Response;
|
||||
use Throwable;
|
||||
use Kiri\Message\Constrict\ResponseInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -15,9 +14,9 @@ interface ExceptionHandlerInterface
|
||||
|
||||
/**
|
||||
* @param Throwable $exception
|
||||
* @param Response $response
|
||||
* @param ResponseInterface $response
|
||||
* @return ResponseInterface
|
||||
*/
|
||||
public function emit(Throwable $exception, Response $response): ResponseInterface;
|
||||
public function emit(Throwable $exception, ResponseInterface $response): ResponseInterface;
|
||||
|
||||
}
|
||||
|
||||
@@ -2,7 +2,16 @@
|
||||
|
||||
namespace Kiri\Router\Interface;
|
||||
|
||||
use Swoole\Http\Request;
|
||||
use Swoole\Http\Response;
|
||||
|
||||
interface OnRequestInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param Response $response
|
||||
*/
|
||||
public function onRequest(Request $request, Response $response): void;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Router\Validator\Inject;
|
||||
namespace Kiri\Router\Interface;
|
||||
|
||||
interface ValidatorInterface
|
||||
{
|
||||
|
||||
+321
-1
@@ -2,7 +2,327 @@
|
||||
|
||||
namespace Kiri\Router;
|
||||
|
||||
class Response
|
||||
use InvalidArgumentException;
|
||||
use Kiri\Di\Context;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
|
||||
class Response implements ResponseInterface
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @var ContentType
|
||||
*/
|
||||
public ContentType $contentType = ContentType::JSON;
|
||||
|
||||
|
||||
/**
|
||||
* @param ContentType $contentType
|
||||
* @return Response
|
||||
*/
|
||||
public function withContentType(ContentType $contentType): static
|
||||
{
|
||||
$this->contentType = $contentType;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $method
|
||||
* @param mixed ...$params
|
||||
* @return mixed
|
||||
*/
|
||||
private function __call__(string $method, ...$params): mixed
|
||||
{
|
||||
if (!Context::exists(ResponseInterface::class)) {
|
||||
$response = Context::set(ResponseInterface::class, new static());
|
||||
} else {
|
||||
$response = Context::get(ResponseInterface::class);
|
||||
}
|
||||
return $response->{$method}(...$params);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the HTTP protocol version as a string.
|
||||
*
|
||||
* The string MUST contain only the HTTP version number (e.g., "1.1", "1.0").
|
||||
*
|
||||
* @return string HTTP protocol version.
|
||||
*/
|
||||
public function getProtocolVersion(): string
|
||||
{
|
||||
// TODO: Implement getProtocolVersion() method.
|
||||
return $this->__call__(__FUNCTION__);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an instance with the specified HTTP protocol version.
|
||||
*
|
||||
* The version string MUST contain only the HTTP version number (e.g.,
|
||||
* "1.1", "1.0").
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return an instance that has the
|
||||
* new protocol version.
|
||||
*
|
||||
* @param string $version HTTP protocol version
|
||||
* @return static
|
||||
*/
|
||||
public function withProtocolVersion(string $version): ResponseInterface
|
||||
{
|
||||
// TODO: Implement withProtocolVersion() method.
|
||||
return $this->__call__(__FUNCTION__, $version);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all message header values.
|
||||
*
|
||||
* The keys represent the header name as it will be sent over the wire, and
|
||||
* each value is an array of strings associated with the header.
|
||||
*
|
||||
* // Represent the headers as a string
|
||||
* foreach ($message->getHeaders() as $name => $values) {
|
||||
* echo $name . ": " . implode(", ", $values);
|
||||
* }
|
||||
*
|
||||
* // Emit headers iteratively:
|
||||
* foreach ($message->getHeaders() as $name => $values) {
|
||||
* foreach ($values as $value) {
|
||||
* header(sprintf('%s: %s', $name, $value), false);
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* While header names are not case-sensitive, getHeaders() will preserve the
|
||||
* exact case in which headers were originally specified.
|
||||
*
|
||||
* @return string[][] Returns an associative array of the message's headers. Each
|
||||
* key MUST be a header name, and each value MUST be an array of strings
|
||||
* for that header.
|
||||
*/
|
||||
public function getHeaders(): array
|
||||
{
|
||||
// TODO: Implement getHeaders() method.
|
||||
return $this->__call__(__FUNCTION__);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a header exists by the given case-insensitive name.
|
||||
*
|
||||
* @param string $name Case-insensitive header field name.
|
||||
* @return bool Returns true if any header names match the given header
|
||||
* name using a case-insensitive string comparison. Returns false if
|
||||
* no matching header name is found in the message.
|
||||
*/
|
||||
public function hasHeader(string $name): bool
|
||||
{
|
||||
// TODO: Implement hasHeader() method.
|
||||
return $this->__call__(__FUNCTION__, $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a message header value by the given case-insensitive name.
|
||||
*
|
||||
* This method returns an array of all the header values of the given
|
||||
* case-insensitive header name.
|
||||
*
|
||||
* If the header does not appear in the message, this method MUST return an
|
||||
* empty array.
|
||||
*
|
||||
* @param string $name Case-insensitive header field name.
|
||||
* @return string[] An array of string values as provided for the given
|
||||
* header. If the header does not appear in the message, this method MUST
|
||||
* return an empty array.
|
||||
*/
|
||||
public function getHeader(string $name): array
|
||||
{
|
||||
// TODO: Implement getHeader() method.
|
||||
return $this->__call__(__FUNCTION__, $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a comma-separated string of the values for a single header.
|
||||
*
|
||||
* This method returns all of the header values of the given
|
||||
* case-insensitive header name as a string concatenated together using
|
||||
* a comma.
|
||||
*
|
||||
* NOTE: Not all header values may be appropriately represented using
|
||||
* comma concatenation. For such headers, use getHeader() instead
|
||||
* and supply your own delimiter when concatenating.
|
||||
*
|
||||
* If the header does not appear in the message, this method MUST return
|
||||
* an empty string.
|
||||
*
|
||||
* @param string $name Case-insensitive header field name.
|
||||
* @return string A string of values as provided for the given header
|
||||
* concatenated together using a comma. If the header does not appear in
|
||||
* the message, this method MUST return an empty string.
|
||||
*/
|
||||
public function getHeaderLine(string $name): string
|
||||
{
|
||||
// TODO: Implement getHeaderLine() method.
|
||||
return $this->__call__(__FUNCTION__, $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an instance with the provided value replacing the specified header.
|
||||
*
|
||||
* While header names are case-insensitive, the casing of the header will
|
||||
* be preserved by this function, and returned from getHeaders().
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return an instance that has the
|
||||
* new and/or updated header and value.
|
||||
*
|
||||
* @param string $name Case-insensitive header field name.
|
||||
* @param string|string[] $value Header value(s).
|
||||
* @return static
|
||||
* @throws InvalidArgumentException for invalid header names or values.
|
||||
*/
|
||||
public function withHeader(string $name, $value): ResponseInterface
|
||||
{
|
||||
// TODO: Implement withHeader() method.
|
||||
return $this->__call__(__FUNCTION__, $name, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an instance with the specified header appended with the given value.
|
||||
*
|
||||
* Existing values for the specified header will be maintained. The new
|
||||
* value(s) will be appended to the existing list. If the header did not
|
||||
* exist previously, it will be added.
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return an instance that has the
|
||||
* new header and/or value.
|
||||
*
|
||||
* @param string $name Case-insensitive header field name to add.
|
||||
* @param string|string[] $value Header value(s).
|
||||
* @return static
|
||||
* @throws InvalidArgumentException for invalid header names or values.
|
||||
*/
|
||||
public function withAddedHeader(string $name, $value): ResponseInterface
|
||||
{
|
||||
// TODO: Implement withAddedHeader() method.
|
||||
return $this->__call__(__FUNCTION__, $name, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an instance without the specified header.
|
||||
*
|
||||
* Header resolution MUST be done without case-sensitivity.
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return an instance that removes
|
||||
* the named header.
|
||||
*
|
||||
* @param string $name Case-insensitive header field name to remove.
|
||||
* @return static
|
||||
*/
|
||||
public function withoutHeader(string $name): ResponseInterface
|
||||
{
|
||||
// TODO: Implement withoutHeader() method.
|
||||
return $this->__call__(__FUNCTION__, $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the body of the message.
|
||||
*
|
||||
* @return StreamInterface Returns the body as a stream.
|
||||
*/
|
||||
public function getBody(): StreamInterface
|
||||
{
|
||||
// TODO: Implement getBody() method.
|
||||
return $this->__call__(__FUNCTION__);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an instance with the specified message body.
|
||||
*
|
||||
* The body MUST be a StreamInterface object.
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return a new instance that has the
|
||||
* new body stream.
|
||||
*
|
||||
* @param StreamInterface $body Body.
|
||||
* @return static
|
||||
* @throws InvalidArgumentException When the body is not valid.
|
||||
*/
|
||||
public function withBody(StreamInterface $body): ResponseInterface
|
||||
{
|
||||
// TODO: Implement withBody() method.
|
||||
return $this->__call__(__FUNCTION__, $body);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the response status code.
|
||||
*
|
||||
* The status code is a 3-digit integer result code of the server's attempt
|
||||
* to understand and satisfy the request.
|
||||
*
|
||||
* @return int Status code.
|
||||
*/
|
||||
public function getStatusCode(): int
|
||||
{
|
||||
// TODO: Implement getStatusCode() method.
|
||||
return $this->__call__(__FUNCTION__);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an instance with the specified status code and, optionally, reason phrase.
|
||||
*
|
||||
* If no reason phrase is specified, implementations MAY choose to default
|
||||
* to the RFC 7231 or IANA recommended reason phrase for the response's
|
||||
* status code.
|
||||
*
|
||||
* This method MUST be implemented in such a way as to retain the
|
||||
* immutability of the message, and MUST return an instance that has the
|
||||
* updated status and reason phrase.
|
||||
*
|
||||
* @link http://tools.ietf.org/html/rfc7231#section-6
|
||||
* @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
|
||||
* @param int $code The 3-digit integer result code to set.
|
||||
* @param string $reasonPhrase The reason phrase to use with the
|
||||
* provided status code; if none is provided, implementations MAY
|
||||
* use the defaults as suggested in the HTTP specification.
|
||||
* @return static
|
||||
* @throws InvalidArgumentException For invalid status code arguments.
|
||||
*/
|
||||
public function withStatus(int $code, string $reasonPhrase = ''): ResponseInterface
|
||||
{
|
||||
// TODO: Implement withStatus() method.
|
||||
return $this->__call__(__FUNCTION__, $code, $reasonPhrase);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the response reason phrase associated with the status code.
|
||||
*
|
||||
* Because a reason phrase is not a required element in a response
|
||||
* status line, the reason phrase value MAY be null. Implementations MAY
|
||||
* choose to return the default RFC 7231 recommended reason phrase (or those
|
||||
* listed in the IANA HTTP Status Code Registry) for the response's
|
||||
* status code.
|
||||
*
|
||||
* @link http://tools.ietf.org/html/rfc7231#section-6
|
||||
* @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
|
||||
* @return string Reason phrase; must return an empty string if none present.
|
||||
*/
|
||||
public function getReasonPhrase(): string
|
||||
{
|
||||
// TODO: Implement getReasonPhrase() method.
|
||||
return $this->__call__(__FUNCTION__);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param object $response
|
||||
* @return void
|
||||
*/
|
||||
public function write(object $response): void
|
||||
{
|
||||
$response->end($this->getBody()->getContents());
|
||||
}
|
||||
}
|
||||
|
||||
+206
@@ -2,7 +2,213 @@
|
||||
|
||||
namespace Kiri\Router;
|
||||
|
||||
use Closure;
|
||||
use Exception;
|
||||
use Kiri;
|
||||
use Kiri\Annotation\Route\RequestMethod;
|
||||
use ReflectionException;
|
||||
|
||||
const ROUTER_TYPE_HTTP = 'http';
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* $component->set([
|
||||
* 'request' => [
|
||||
* 'middlewares' => []
|
||||
* ]
|
||||
* ])
|
||||
*/
|
||||
class Router
|
||||
{
|
||||
const METHODS = [];
|
||||
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private static string $type = ROUTER_TYPE_HTTP;
|
||||
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param Closure $closure
|
||||
*/
|
||||
public static function addServer(string $name, Closure $closure): void
|
||||
{
|
||||
static::$type = $name;
|
||||
$closure();
|
||||
static::$type = ROUTER_TYPE_HTTP;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Closure $handler
|
||||
*/
|
||||
public static function jsonp(Closure $handler): void
|
||||
{
|
||||
static::$type = 'json-rpc';
|
||||
$handler();
|
||||
static::$type = ROUTER_TYPE_HTTP;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $route
|
||||
* @param string|Closure $handler
|
||||
* @throws
|
||||
*/
|
||||
public static function post(string $route, string|Closure $handler): void
|
||||
{
|
||||
$router = Kiri::getDi()->get(DataGrip::class)->get(static::$type);
|
||||
$router->addRoute([RequestMethod::REQUEST_POST], $route, $handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $route
|
||||
* @param string|Closure $handler
|
||||
* @throws
|
||||
*/
|
||||
public static function get(string $route, string|Closure $handler): void
|
||||
{
|
||||
$router = Kiri::getDi()->get(DataGrip::class)->get(static::$type);
|
||||
$router->addRoute([RequestMethod::REQUEST_GET], $route, $handler);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $route
|
||||
* @param string|Closure $handler
|
||||
* @throws
|
||||
*/
|
||||
public static function options(string $route, string|Closure $handler): void
|
||||
{
|
||||
$router = Kiri::getDi()->get(DataGrip::class)->get(static::$type);
|
||||
$router->addRoute([RequestMethod::REQUEST_OPTIONS], $route, $handler);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $route
|
||||
* @param string|Closure $handler
|
||||
* @throws
|
||||
*/
|
||||
public static function any(string $route, string|Closure $handler): void
|
||||
{
|
||||
$router = Kiri::getDi()->get(DataGrip::class)->get(static::$type);
|
||||
$router->addRoute(self::METHODS, $route, $handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $route
|
||||
* @param string|Closure $handler
|
||||
* @throws
|
||||
*/
|
||||
public static function delete(string $route, string|Closure $handler): void
|
||||
{
|
||||
$router = Kiri::getDi()->get(DataGrip::class)->get(static::$type);
|
||||
$router->addRoute([RequestMethod::REQUEST_DELETE], $route, $handler);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $route
|
||||
* @param string|Closure $handler
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
public static function head(string $route, string|Closure $handler): void
|
||||
{
|
||||
$router = Kiri::getDi()->get(DataGrip::class)->get(static::$type);
|
||||
$router->addRoute([RequestMethod::REQUEST_HEAD], $route, $handler);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $route
|
||||
* @param string|Closure $handler
|
||||
* @throws
|
||||
*/
|
||||
public static function put(string $route, string|Closure $handler): void
|
||||
{
|
||||
$router = Kiri::getDi()->get(DataGrip::class)->get(static::$type);
|
||||
$router->addRoute([RequestMethod::REQUEST_PUT], $route, $handler);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array|RequestMethod $methods
|
||||
* @param string $route
|
||||
* @param array|string|Closure $handler
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
public static function addRoute(array|RequestMethod $methods, string $route, array|string|Closure $handler): void
|
||||
{
|
||||
$router = Kiri::getDi()->get(DataGrip::class)->get(static::$type);
|
||||
if ($methods instanceof RequestMethod) {
|
||||
$methods = [$methods];
|
||||
}
|
||||
$router->addRoute($methods, $route, $handler);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $config
|
||||
* @param Closure $closure
|
||||
* @throws
|
||||
*/
|
||||
public static function group(array $config, Closure $closure): void
|
||||
{
|
||||
$router = Kiri::getDi()->get(DataGrip::class)->get(static::$type);
|
||||
|
||||
$router->groupTack[] = $config;
|
||||
|
||||
call_user_func($closure);
|
||||
|
||||
array_pop($router->groupTack);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function scan_build_route(): void
|
||||
{
|
||||
scan_directory(APP_PATH, 'App');
|
||||
|
||||
$this->read_dir_file(APP_PATH . 'routes');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
private function read_dir_file($path): void
|
||||
{
|
||||
$files = glob($path . '/*');
|
||||
for ($i = 0; $i < count($files); $i++) {
|
||||
$file = $files[$i];
|
||||
if (is_dir($file)) {
|
||||
$this->read_dir_file($file);
|
||||
} else {
|
||||
$this->resolve_file($file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $files
|
||||
* @throws Exception
|
||||
*/
|
||||
private function resolve_file($files): void
|
||||
{
|
||||
try {
|
||||
include "$files";
|
||||
} catch (\Throwable $throwable) {
|
||||
var_dump($throwable->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+89
-273
@@ -1,34 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Message\Handler;
|
||||
namespace Kiri\Router;
|
||||
|
||||
|
||||
use Closure;
|
||||
use Exception;
|
||||
use Kiri;
|
||||
use Kiri\Annotation\Inject;
|
||||
use Kiri\Exception\ConfigException;
|
||||
use Kiri\Message\Handler\Abstracts\MiddlewareManager;
|
||||
use Kiri\Message\Handler\TreeHelper\HashTree;
|
||||
use Kiri\Message\Handler\TreeHelper\MethodDelete;
|
||||
use Kiri\Message\Handler\TreeHelper\MethodGet;
|
||||
use Kiri\Message\Handler\TreeHelper\MethodHead;
|
||||
use Kiri\Message\Handler\TreeHelper\MethodOptions;
|
||||
use Kiri\Message\Handler\TreeHelper\MethodPut;
|
||||
use Kiri\Message\Handler\TreeHelper\MethodPost;
|
||||
use Kiri\Message\Handler\TreeHelper\TreeLeafInterface;
|
||||
use Psr\Http\Server\MiddlewareInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Kiri\Router\Base\NotFoundController;
|
||||
use ReflectionException;
|
||||
use Throwable;
|
||||
use Traversable;
|
||||
use Kiri\Router\Base\Middleware;
|
||||
use Kiri\Core\HashMap;
|
||||
use Kiri\Annotation\Route\RequestMethod;
|
||||
|
||||
|
||||
const REQUEST_METHODS = [
|
||||
'PUT' => new MethodPut()
|
||||
];
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@@ -39,41 +25,18 @@ class RouterCollector implements \ArrayAccess, \IteratorAggregate
|
||||
private array $_item = [];
|
||||
|
||||
|
||||
private array $reflex = [];
|
||||
|
||||
|
||||
/**
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
#[Inject(LoggerInterface::class)]
|
||||
public LoggerInterface $logger;
|
||||
|
||||
|
||||
private array $globalMiddlewares = [];
|
||||
|
||||
|
||||
public array $groupTack = [];
|
||||
|
||||
|
||||
/**
|
||||
* @var array
|
||||
* @var HashMap
|
||||
*/
|
||||
private array $methods = [];
|
||||
private HashMap $methods;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->methods = [
|
||||
RequestMethod::REQUEST_DELETE->getString() => di(MethodDelete::class),
|
||||
RequestMethod::REQUEST_PUT->getString() => di(MethodPut::class),
|
||||
RequestMethod::REQUEST_POST->getString() => di(MethodPost::class),
|
||||
RequestMethod::REQUEST_OPTIONS->getString() => di(MethodOptions::class),
|
||||
RequestMethod::REQUEST_GET->getString() => di(MethodGet::class),
|
||||
RequestMethod::REQUEST_HEAD->getString() => di(MethodHead::class),
|
||||
];
|
||||
$this->methods = new HashMap();
|
||||
}
|
||||
|
||||
|
||||
@@ -86,178 +49,140 @@ class RouterCollector implements \ArrayAccess, \IteratorAggregate
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return array<MiddlewareInterface>
|
||||
*/
|
||||
public function getGlobalMiddlewares(): array
|
||||
{
|
||||
return $this->globalMiddlewares;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $handler
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function addGlobalMiddlewares(string $handler): void
|
||||
{
|
||||
$handler = Kiri::getDi()->get($handler);
|
||||
if (!in_array(MiddlewareInterface::class, class_implements($handler))) {
|
||||
throw new Exception('The Middleware must instance ' . MiddlewareInterface::class);
|
||||
}
|
||||
$this->globalMiddlewares[] = $handler;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param RequestMethod[] $method
|
||||
* @param string $route
|
||||
* @param string|Closure|array $closure
|
||||
* @param string|Closure $closure
|
||||
* @throws
|
||||
*/
|
||||
public function addRoute(array $method, string $route, string|Closure|array $closure)
|
||||
public function addRoute(array $method, string $route, string|Closure $closure)
|
||||
{
|
||||
try {
|
||||
$route = $this->_splicing_routing($route);
|
||||
$middlewares = Kiri\Abstracts\Config::get('request.middlewares', []);
|
||||
$interpreter = Kiri::getDi()->get(ControllerInterpreter::class);
|
||||
if ($closure instanceof Closure) {
|
||||
$middlewares = $this->_getRouteMiddlewares($middlewares);
|
||||
} else if (is_string($closure)) {
|
||||
$this->_route_analysis($closure);
|
||||
$handler = $interpreter->addRouteByClosure($closure);
|
||||
} else {
|
||||
$handler = $this->resolve($closure, $interpreter);
|
||||
}
|
||||
foreach ($method as $value) {
|
||||
$this->register($route, $value->getString(), $closure, $middlewares);
|
||||
if ($value instanceof RequestMethod) {
|
||||
$value = $value->getString();
|
||||
}
|
||||
$this->register($route, $value, $handler);
|
||||
}
|
||||
} catch (Throwable $throwable) {
|
||||
$this->logger->error($throwable->getMessage(), [throwable($throwable)]);
|
||||
error($throwable->getMessage(), [throwable($throwable)]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $closure
|
||||
* @param ControllerInterpreter $interpreter
|
||||
* @return Handler
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
private function resolve(string $closure, ControllerInterpreter $interpreter): Handler
|
||||
{
|
||||
[$className, $method] = explode('@', $closure);
|
||||
|
||||
$class = Kiri::getDi()->get($this->resetName($className));
|
||||
|
||||
return $interpreter->addRouteByString($class, $method);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $className
|
||||
* @return string
|
||||
*/
|
||||
private function resetName(string $className): string
|
||||
{
|
||||
$namespace = array_filter(array_column($this->groupTack, 'namespace'));
|
||||
if (count($namespace) < 1) {
|
||||
return $className;
|
||||
}
|
||||
return implode('\\', $namespace) . '\\' . $className;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param string $method
|
||||
* @param $closure
|
||||
* @param $middlewares
|
||||
* @param Handler $handler
|
||||
* @return void
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
public function register(string $path, string $method, $closure, $middlewares): void
|
||||
public function register(string $path, string $method, Handler $handler): void
|
||||
{
|
||||
$end = $this->methods[$method];
|
||||
|
||||
$json = str_split($path, 4);
|
||||
|
||||
$handler = new Handler($path, $closure, $middlewares);
|
||||
foreach ($json as $item) {
|
||||
/** @var TreeLeafInterface $leaf */
|
||||
$leaf = new ($end::class)($item);
|
||||
$leaf->setPath($item);
|
||||
if (!$end->hasLeaf()) {
|
||||
$end = $end->addLeaf($item, $leaf);
|
||||
$hashMap = HashMap::Tree($this->methods, $method);
|
||||
foreach (str_split($path, 4) as $item) {
|
||||
if ($hashMap->has($item)) {
|
||||
$hashMap = $hashMap->get($item);
|
||||
} else {
|
||||
$search = $end->searchLeaf($item);
|
||||
if ($search == null) {
|
||||
$end = $end->addLeaf($item, $leaf);
|
||||
} else {
|
||||
$end = $search;
|
||||
$hashMap = new HashMap();
|
||||
$hashMap->put($item, $hashMap);
|
||||
}
|
||||
}
|
||||
$hashMap->put('handler', $handler);
|
||||
$this->registerMiddleware($path);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @return void
|
||||
* @throws ReflectionException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function registerMiddleware(string $path): void
|
||||
{
|
||||
$middlewares = array_column($this->groupTack, 'middleware');
|
||||
if (count($middlewares) > 0) {
|
||||
$manager = Kiri::getDi()->get(Middleware::class);
|
||||
foreach ($middlewares as $middleware) {
|
||||
if (is_string($middleware)) {
|
||||
$middleware = [$middleware];
|
||||
}
|
||||
foreach ($middleware as $value) {
|
||||
$manager->addPathMiddleware($path, $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
$end->setHandler($handler);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param string $method
|
||||
* @return HashTree|null
|
||||
* @throws ConfigException
|
||||
* @throws ReflectionException
|
||||
* @return Handler|null
|
||||
*/
|
||||
public function query(string $path, string $method): ?Handler
|
||||
{
|
||||
$parent = $this->methods[$method];
|
||||
|
||||
$string = str_split($path, 4);
|
||||
foreach ($string as $item) {
|
||||
$parent = $parent->searchLeaf($item);
|
||||
if (!$this->methods->has($method)) {
|
||||
return $this->NotFundHandler($path);
|
||||
}
|
||||
$parent = $this->methods->get($method);
|
||||
foreach (str_split($path, 4) as $item) {
|
||||
$parent = $parent->get($item);
|
||||
if ($parent === null) {
|
||||
return $this->NotFundHandler($path);
|
||||
}
|
||||
}
|
||||
return $parent->getHandler();
|
||||
return $parent->get('handler');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @return Handler
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
private function NotFundHandler(string $path): Handler
|
||||
{
|
||||
$middlewares = Kiri\Abstracts\Config::get('request.middlewares', []);
|
||||
|
||||
return new Handler($path, [NotFoundController::class, 'fail'], $middlewares);
|
||||
return new Handler([NotFoundController::class, 'fail'], []);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $closure
|
||||
* @throws Exception
|
||||
*/
|
||||
private function _route_analysis(string &$closure)
|
||||
{
|
||||
$closure = explode('@', $closure);
|
||||
$closure[0] = $this->addNamespace($closure[0]);
|
||||
if (class_exists($closure[0])) {
|
||||
$this->_registerMiddleware($closure[0], $closure[1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $middlewares
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
private function _getRouteMiddlewares(array $middlewares = []): array
|
||||
{
|
||||
$middleware = array_column($this->groupTack, 'middleware');
|
||||
if (count($middleware = array_filter($middleware)) > 0) {
|
||||
foreach ($middleware as $value) {
|
||||
if (is_string($value)) {
|
||||
$value = [$value];
|
||||
}
|
||||
foreach ($value as $item) {
|
||||
if (!in_array(MiddlewareInterface::class, class_implements($item, true))) {
|
||||
throw new Exception("middleware handler must instance MiddlewareInterface::class");
|
||||
}
|
||||
$middlewares[] = $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $middlewares;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
* @param string $method
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
private function _registerMiddleware(string $class, string $method): void
|
||||
{
|
||||
$middleware = $this->_getRouteMiddlewares();
|
||||
foreach ($middleware as $value) {
|
||||
MiddlewareManager::add($class, $method, $value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $route
|
||||
* @return string
|
||||
@@ -273,115 +198,6 @@ class RouterCollector implements \ArrayAccess, \IteratorAggregate
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $closure
|
||||
* @param $route
|
||||
* @return array
|
||||
* @throws ReflectionException
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function loadMiddlewares($closure, $route): array
|
||||
{
|
||||
$middlewares = [];
|
||||
$close = new \ReflectionFunction($closure);
|
||||
if (!empty($close->getClosureThis()) && env('environmental_workerId') == 0) {
|
||||
$this->logger->warning('[' . $route . '] Static functions are recommended as callback functions.');
|
||||
}
|
||||
$middleware = array_column($this->groupTack, 'middleware');
|
||||
$middleware = array_unique($middleware);
|
||||
if (!empty($middleware = array_filter($middleware))) {
|
||||
foreach ($middleware as $mi) {
|
||||
if (!is_array($mi)) {
|
||||
$mi = [$mi];
|
||||
}
|
||||
foreach ($mi as $item) {
|
||||
if (!in_array(MiddlewareInterface::class, class_implements($item))) {
|
||||
throw new Exception('The Middleware must instance ' . MiddlewareInterface::class);
|
||||
}
|
||||
$middlewares[$item] = $item;
|
||||
}
|
||||
}
|
||||
$middlewares = array_values($middlewares);
|
||||
}
|
||||
return $middlewares;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $class
|
||||
* @return string|null
|
||||
*/
|
||||
protected function addNamespace($class): ?string
|
||||
{
|
||||
$middleware = array_column($this->groupTack, 'namespace');
|
||||
if (empty($middleware = array_filter($middleware))) {
|
||||
return $class;
|
||||
}
|
||||
$middleware[] = $class;
|
||||
return implode('\\', array_map(function ($value) {
|
||||
return trim($value, '\\');
|
||||
}, $middleware));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param string $method
|
||||
* @return Handler|int|null
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
public function find(string $path, string $method): Handler|int|null
|
||||
{
|
||||
$dispatcher = match ($method) {
|
||||
'OPTIONS' => $this->options($path, $method),
|
||||
default => $this->other($path, $method)
|
||||
};
|
||||
if (is_null($dispatcher)) {
|
||||
$middlewares = Kiri\Abstracts\Config::get('request.middlewares', []);
|
||||
|
||||
$dispatcher = new Handler($path, [NotFoundController::class, 'fail'], $middlewares);
|
||||
} else if (is_integer($dispatcher)) {
|
||||
$middlewares = Kiri\Abstracts\Config::get('request.middlewares', []);
|
||||
|
||||
$dispatcher = new Handler($path, [MethodErrorController::class, 'fail'], $middlewares);
|
||||
}
|
||||
return $dispatcher;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
* @param $method
|
||||
* @return int|mixed
|
||||
*/
|
||||
public function other($path, $method): mixed
|
||||
{
|
||||
if (!isset($this->_item[$path])) {
|
||||
return 404;
|
||||
}
|
||||
$handler = $this->_item[$path][$method] ?? null;
|
||||
if (is_null($handler)) {
|
||||
return 405;
|
||||
}
|
||||
return $handler;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
* @param $method
|
||||
* @return int|mixed
|
||||
*/
|
||||
public function options($path, $method): mixed
|
||||
{
|
||||
$handler = $this->_item[$path][$method] ?? null;
|
||||
if (is_null($handler)) {
|
||||
return $this->_item['/*'][$method] ?? 405;
|
||||
}
|
||||
return $handler;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param mixed $offset
|
||||
* @return bool
|
||||
|
||||
+29
-64
@@ -1,35 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Message;
|
||||
namespace Kiri\Router;
|
||||
|
||||
|
||||
use Exception;
|
||||
use Kiri;
|
||||
use Kiri\Abstracts\AbstractServer;
|
||||
use Kiri\Abstracts\Config;
|
||||
use Kiri\Abstracts\CoordinatorManager;
|
||||
use Kiri\Coordinator;
|
||||
use Kiri\Di\ContainerInterface;
|
||||
use Kiri\Di\Context;
|
||||
use Kiri\Events\EventProvider;
|
||||
use Kiri\Exception\ConfigException;
|
||||
use Kiri\Message\Abstracts\ExceptionHandlerInterface;
|
||||
use Kiri\Message\Abstracts\ResponseHelper;
|
||||
use Kiri\Message\Constrict\RequestInterface;
|
||||
use Kiri\Message\Constrict\ResponseInterface;
|
||||
use Kiri\Message\Handler\DataGrip;
|
||||
use Kiri\Message\Handler\Dispatcher;
|
||||
use Kiri\Message\Handler\RouterCollector;
|
||||
use Kiri\Message\Response as Psr7Response;
|
||||
use Kiri\Server\Events\OnAfterWorkerStart;
|
||||
use Kiri\Server\Events\OnBeforeWorkerStart;
|
||||
use Kiri\Router\Interface\ExceptionHandlerInterface;
|
||||
use Psr\Container\ContainerExceptionInterface;
|
||||
use Psr\Container\NotFoundExceptionInterface;
|
||||
use Psr\Http\Message\ResponseInterface as PsrResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Swoole\Http\Request;
|
||||
use Swoole\Http\Response;
|
||||
use Kiri\Router\Constrict\Response as KrcResponse;
|
||||
use Kiri\Router\Constrict\Uri;
|
||||
use Kiri\Router\Interface\OnRequestInterface;
|
||||
use Kiri\Router\Base\ExceptionHandlerDispatcher;
|
||||
|
||||
|
||||
/**
|
||||
@@ -38,8 +28,6 @@ use Swoole\Http\Response;
|
||||
class Server extends AbstractServer implements OnRequestInterface
|
||||
{
|
||||
|
||||
use ResponseHelper;
|
||||
|
||||
public RouterCollector $router;
|
||||
|
||||
|
||||
@@ -48,25 +36,21 @@ class Server extends AbstractServer implements OnRequestInterface
|
||||
*/
|
||||
public ExceptionHandlerInterface $exception;
|
||||
|
||||
|
||||
private ContentType $contentType;
|
||||
|
||||
public Emitter $emitter;
|
||||
/**
|
||||
* @var HttpResponseEmitter
|
||||
*/
|
||||
public HttpResponseEmitter $emitter;
|
||||
|
||||
|
||||
/**
|
||||
* @param ContainerInterface $container
|
||||
* @param Dispatcher $dispatcher
|
||||
* @param EventProvider $provider
|
||||
* @param DataGrip $dataGrip
|
||||
* @param array $config
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct(
|
||||
public ContainerInterface $container,
|
||||
public Dispatcher $dispatcher,
|
||||
public EventProvider $provider,
|
||||
public DataGrip $dataGrip,
|
||||
array $config = [])
|
||||
{
|
||||
parent::__construct($config);
|
||||
@@ -80,37 +64,15 @@ class Server extends AbstractServer implements OnRequestInterface
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
$this->emitter = $this->container->get(Emitter::class);
|
||||
$this->emitter = $this->container->get(HttpResponseEmitter::class);
|
||||
|
||||
$exception = Config::get('exception.http', ExceptionHandlerDispatcher::class);
|
||||
$exception = Kiri::service()->get('request')->exception;
|
||||
if (!in_array(ExceptionHandlerInterface::class, class_implements($exception))) {
|
||||
$exception = ExceptionHandlerDispatcher::class;
|
||||
}
|
||||
$this->exception = $this->container->get($exception);
|
||||
|
||||
$this->provider->on(OnBeforeWorkerStart::class, [$this, 'onStartWaite']);
|
||||
$this->provider->on(OnAfterWorkerStart::class, [$this, 'onEndWaite']);
|
||||
|
||||
$this->contentType = Config::get('response.format', ContentType::JSON);
|
||||
$this->router = $this->dataGrip->get('http');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function onStartWaite(): void
|
||||
{
|
||||
CoordinatorManager::utility(Coordinator::WORKER_START)->waite();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function onEndWaite(): void
|
||||
{
|
||||
CoordinatorManager::utility(Coordinator::WORKER_START)->done();
|
||||
$this->router = $this->container->get(DataGrip::class)->get(ROUTER_TYPE_HTTP);
|
||||
}
|
||||
|
||||
|
||||
@@ -127,30 +89,33 @@ class Server extends AbstractServer implements OnRequestInterface
|
||||
|
||||
$dispatcher = $this->router->query($request->server['request_uri'], $request->getMethod());
|
||||
|
||||
$PsrResponse = $dispatcher->dispatch->recover($PsrRequest);
|
||||
$PsrResponse = (new HttpRequestHandler([], $dispatcher))->handle($PsrRequest);
|
||||
} catch (\Throwable $throwable) {
|
||||
$this->logger->error($throwable->getMessage(), [$throwable]);
|
||||
$PsrResponse = $this->exception->emit($throwable, di(Constrict\Response::class));
|
||||
} finally {
|
||||
$this->emitter->sender($response, $PsrResponse);
|
||||
$this->emitter->sender($PsrResponse, $response);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @return RequestInterface
|
||||
* @throws Exception
|
||||
*/
|
||||
private function initRequestAndResponse(Request $request): \Psr\Http\Message\RequestInterface
|
||||
private function initRequestAndResponse(Request $request): RequestInterface
|
||||
{
|
||||
/** @var ResponseInterface $PsrResponse */
|
||||
$PsrResponse = Context::set(ResponseInterface::class, new Psr7Response());
|
||||
$PsrResponse->withContentType($this->contentType);
|
||||
/** @var \Kiri\Router\Response $response */
|
||||
$response = Kiri::service()->get('response');
|
||||
|
||||
$serverRequest = (new ServerRequest())->withData($request->getContent())
|
||||
->withServerParams($request->server)
|
||||
->withServerTarget($request)
|
||||
/** @var KrcResponse $PsrResponse */
|
||||
$PsrResponse = Context::set(ResponseInterface::class, new KrcResponse());
|
||||
$PsrResponse->withContentType($response->contentType);
|
||||
|
||||
$serverRequest = (new ServerRequest())->withHeaders($request->getData())
|
||||
->withUri(Uri::parse($request))
|
||||
->withProtocolVersion($request->server['server_protocol'])
|
||||
->withCookieParams($request->cookie ?? [])
|
||||
->withQueryParams($request->get)
|
||||
->withUploadedFiles($request->files)
|
||||
|
||||
+45
-1
@@ -3,6 +3,9 @@
|
||||
namespace Kiri\Router;
|
||||
|
||||
use Kiri\Di\Context;
|
||||
use Kiri\Message\Stream;
|
||||
use Kiri\Router\Base\ExceptionHandlerDispatcher;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
use Psr\Http\Message\UriInterface;
|
||||
@@ -11,10 +14,19 @@ use Psr\Http\Message\UriInterface;
|
||||
/**
|
||||
* @property-read bool $isPost
|
||||
*/
|
||||
class Request implements ServerRequestInterface
|
||||
class ServerRequest implements ServerRequestInterface
|
||||
{
|
||||
|
||||
|
||||
public array $middlewares = [];
|
||||
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public string $exception = ExceptionHandlerDispatcher::class;
|
||||
|
||||
|
||||
/**
|
||||
* @param string $method
|
||||
* @param mixed ...$params
|
||||
@@ -175,6 +187,38 @@ class Request implements ServerRequestInterface
|
||||
return $this->__call__(__FUNCTION__, $name, $value);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $data
|
||||
* @return ServerRequestInterface
|
||||
*/
|
||||
public function withHeaders(string $data): ServerRequestInterface
|
||||
{
|
||||
$headers = explode("\r\n\r\n", $data);
|
||||
$headers = explode("\r\n", $headers[0]);
|
||||
foreach ($headers as $header) {
|
||||
$keyValue = explode(': ', $header);
|
||||
if (!isset($keyValue[1])) {
|
||||
$keyValue[1] = '';
|
||||
}
|
||||
$keyValue[1] = explode(', ', $keyValue[1]);
|
||||
$this->withHeader(...$keyValue);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param string|null $default
|
||||
* @return string|null
|
||||
*/
|
||||
public function header(string $name, ?string $default = null): ?string
|
||||
{
|
||||
return $this->__call__(__FUNCTION__, $name, $default);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return an instance with the specified header appended with the given value.
|
||||
*
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace Kiri\Router;
|
||||
|
||||
class ChunkResponse extends Response
|
||||
class StreamResponse extends Response
|
||||
{
|
||||
|
||||
public int $limit;
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Inject\Validator\Inject;
|
||||
namespace Kiri\Router\Validator\Inject;
|
||||
|
||||
use Exception;
|
||||
use Kiri\Inject\Route\LocalService;
|
||||
use ReflectionException;
|
||||
use Kiri\Inject\Route\Container;
|
||||
use Kiri\Router\Interface\ValidatorInterface;
|
||||
|
||||
#[\Attribute(\Attribute::TARGET_PROPERTY)]
|
||||
class Email implements ValidatorInterface
|
||||
@@ -22,19 +19,12 @@ class Email implements ValidatorInterface
|
||||
|
||||
|
||||
/**
|
||||
* @param object $class
|
||||
* @param string $name
|
||||
* @return bool
|
||||
* @throws ReflectionException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function dispatch(string $name): bool
|
||||
public function dispatch(object $class, string $name): bool
|
||||
{
|
||||
// TODO: Implement dispatch() method.
|
||||
$service = Container::getContext()->get(LocalService::class)->get('request');
|
||||
if ($service->isPost) {
|
||||
return filter_var($service->post($name, null), FILTER_VALIDATE_EMAIL);
|
||||
} else {
|
||||
return filter_var($service->query($name, null), FILTER_VALIDATE_EMAIL);
|
||||
}
|
||||
return filter_var($class->{$name}, FILTER_VALIDATE_EMAIL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Inject\Validator\Inject;
|
||||
namespace Kiri\Router\Validator\Inject;
|
||||
|
||||
use Kiri\Router\Interface\ValidatorInterface;
|
||||
|
||||
#[\Attribute(\Attribute::TARGET_PROPERTY)]
|
||||
class Ignore implements ValidatorInterface
|
||||
@@ -8,12 +10,12 @@ class Ignore implements ValidatorInterface
|
||||
|
||||
|
||||
/**
|
||||
* @param object $class
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public function dispatch(string $name): bool
|
||||
public function dispatch(object $class, string $name): bool
|
||||
{
|
||||
// TODO: Implement dispatch() method.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Inject\Validator\Inject;
|
||||
namespace Kiri\Router\Validator\Inject;
|
||||
|
||||
use Kiri\Router\Interface\ValidatorInterface;
|
||||
|
||||
#[\Attribute(\Attribute::TARGET_PROPERTY)]
|
||||
class In implements ValidatorInterface
|
||||
@@ -16,12 +18,12 @@ class In implements ValidatorInterface
|
||||
|
||||
|
||||
/**
|
||||
* @param object $class
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public function dispatch(string $name): bool
|
||||
public function dispatch(object $class, string $name): bool
|
||||
{
|
||||
// TODO: Implement dispatch() method.
|
||||
return true;
|
||||
return in_array($class->{$name}, $this->value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Inject\Validator\Inject;
|
||||
namespace Kiri\Router\Validator\Inject;
|
||||
|
||||
use Kiri\Router\Interface\ValidatorInterface;
|
||||
|
||||
#[\Attribute(\Attribute::TARGET_PROPERTY)]
|
||||
class Length implements ValidatorInterface
|
||||
@@ -16,12 +18,13 @@ class Length implements ValidatorInterface
|
||||
|
||||
|
||||
/**
|
||||
* @param object $class
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public function dispatch(string $name): bool
|
||||
public function dispatch(object $class, string $name): bool
|
||||
{
|
||||
// TODO: Implement dispatch() method.
|
||||
return true;
|
||||
return mb_strlen($class->{$name}) === $this->value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Inject\Validator\Inject;
|
||||
namespace Kiri\Router\Validator\Inject;
|
||||
|
||||
use Kiri\Router\Interface\ValidatorInterface;
|
||||
|
||||
#[\Attribute(\Attribute::TARGET_PROPERTY)]
|
||||
class Max implements ValidatorInterface
|
||||
@@ -17,12 +18,13 @@ class Max implements ValidatorInterface
|
||||
|
||||
|
||||
/**
|
||||
* @param object $class
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public function dispatch(string $name): bool
|
||||
public function dispatch(object $class, string $name): bool
|
||||
{
|
||||
// TODO: Implement dispatch() method.
|
||||
return true;
|
||||
return $class->{$name} <= $this->value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Inject\Validator\Inject;
|
||||
namespace Kiri\Router\Validator\Inject;
|
||||
|
||||
use Kiri\Router\Interface\ValidatorInterface;
|
||||
|
||||
#[\Attribute(\Attribute::TARGET_PROPERTY)]
|
||||
class MaxLength implements ValidatorInterface
|
||||
@@ -16,12 +18,13 @@ class MaxLength implements ValidatorInterface
|
||||
|
||||
|
||||
/**
|
||||
* @param object $class
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public function dispatch(string $name): bool
|
||||
public function dispatch(object $class, string $name): bool
|
||||
{
|
||||
// TODO: Implement dispatch() method.
|
||||
return true;
|
||||
return mb_strlen($class->{$name}) <= $this->value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Inject\Validator\Inject;
|
||||
namespace Kiri\Router\Validator\Inject;
|
||||
|
||||
use Kiri\Router\Interface\ValidatorInterface;
|
||||
|
||||
#[\Attribute(\Attribute::TARGET_PROPERTY)]
|
||||
class Min implements ValidatorInterface
|
||||
@@ -17,12 +18,13 @@ class Min implements ValidatorInterface
|
||||
|
||||
|
||||
/**
|
||||
* @param object $class
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public function dispatch(string $name): bool
|
||||
public function dispatch(object $class, string $name): bool
|
||||
{
|
||||
// TODO: Implement dispatch() method.
|
||||
return true;
|
||||
return $class->{$name} >= $this->value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Inject\Validator\Inject;
|
||||
namespace Kiri\Router\Validator\Inject;
|
||||
|
||||
use Kiri\Router\Interface\ValidatorInterface;
|
||||
|
||||
#[\Attribute(\Attribute::TARGET_PROPERTY)]
|
||||
class MinLength implements ValidatorInterface
|
||||
@@ -16,12 +18,13 @@ class MinLength implements ValidatorInterface
|
||||
|
||||
|
||||
/**
|
||||
* @param object $class
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public function dispatch(string $name): bool
|
||||
public function dispatch(object $class, string $name): bool
|
||||
{
|
||||
// TODO: Implement dispatch() method.
|
||||
return true;
|
||||
return mb_strlen($class->{$name}) <= $this->value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Inject\Validator\Inject;
|
||||
namespace Kiri\Router\Validator\Inject;
|
||||
|
||||
|
||||
use Kiri\Router\Interface\ValidatorInterface;
|
||||
|
||||
#[\Attribute(\Attribute::TARGET_PROPERTY)]
|
||||
class Must implements ValidatorInterface
|
||||
{
|
||||
@@ -17,13 +19,14 @@ class Must implements ValidatorInterface
|
||||
|
||||
|
||||
/**
|
||||
* @param object $class
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public function dispatch(string $name): bool
|
||||
public function dispatch(object $class, string $name): bool
|
||||
{
|
||||
// TODO: Implement dispatch() method.
|
||||
return true;
|
||||
return $class->{$name} === $this->value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,18 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Inject\Validator\Inject;
|
||||
namespace Kiri\Router\Validator\Inject;
|
||||
|
||||
use Kiri\Router\Interface\ValidatorInterface;
|
||||
|
||||
#[\Attribute(\Attribute::TARGET_PROPERTY)]
|
||||
class NotEmpty implements ValidatorInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @param object $class
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public function dispatch(string $name): bool
|
||||
public function dispatch(object $class, string $name): bool
|
||||
{
|
||||
// TODO: Implement dispatch() method.
|
||||
return true;
|
||||
return !empty($class->{$name});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Inject\Validator\Inject;
|
||||
namespace Kiri\Router\Validator\Inject;
|
||||
|
||||
use Kiri\Router\Interface\ValidatorInterface;
|
||||
|
||||
|
||||
#[\Attribute(\Attribute::TARGET_PROPERTY)]
|
||||
@@ -17,12 +19,13 @@ class NotIn implements ValidatorInterface
|
||||
|
||||
|
||||
/**
|
||||
* @param object $class
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public function dispatch(string $name): bool
|
||||
public function dispatch(object $class, string $name): bool
|
||||
{
|
||||
// TODO: Implement dispatch() method.
|
||||
return true;
|
||||
return !in_array($class->{$name}, $this->value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Inject\Validator\Inject;
|
||||
namespace Kiri\Router\Validator\Inject;
|
||||
|
||||
use Kiri\Router\Interface\ValidatorInterface;
|
||||
|
||||
#[\Attribute(\Attribute::TARGET_PROPERTY)]
|
||||
class NotNull implements ValidatorInterface
|
||||
@@ -8,12 +10,13 @@ class NotNull implements ValidatorInterface
|
||||
|
||||
|
||||
/**
|
||||
* @param object $class
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public function dispatch(string $name): bool
|
||||
public function dispatch(object $class, string $name): bool
|
||||
{
|
||||
// TODO: Implement dispatch() method.
|
||||
return true;
|
||||
return $class->{$name} !== null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Inject\Validator\Inject;
|
||||
namespace Kiri\Router\Validator\Inject;
|
||||
|
||||
use Exception;
|
||||
use Kiri\Inject\Route\LocalService;
|
||||
use ReflectionException;
|
||||
use Kiri\Inject\Route\Container;
|
||||
use Kiri\Router\Interface\ValidatorInterface;
|
||||
|
||||
#[\Attribute(\Attribute::TARGET_PROPERTY)]
|
||||
class Phone implements ValidatorInterface
|
||||
@@ -13,20 +10,12 @@ class Phone implements ValidatorInterface
|
||||
const REG = '/^1[356789]\d{9}$/';
|
||||
|
||||
/**
|
||||
* @param object $class
|
||||
* @param string $name
|
||||
* @return bool
|
||||
* @throws ReflectionException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function dispatch(string $name): bool
|
||||
public function dispatch(object $class, string $name): bool
|
||||
{
|
||||
// TODO: Implement dispatch() method.
|
||||
$service = Container::getContext()->get(LocalService::class)->get('request');
|
||||
if ($service->isPost) {
|
||||
$data = $service->post($name, null);
|
||||
} else {
|
||||
$data = $service->query($name, null);
|
||||
}
|
||||
return preg_match(self::REG, $data);
|
||||
return preg_match(self::REG, $class->{$name});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Inject\Validator\Inject;
|
||||
namespace Kiri\Router\Validator\Inject;
|
||||
|
||||
use Kiri\Router\Interface\ValidatorInterface;
|
||||
|
||||
#[\Attribute(\Attribute::TARGET_PROPERTY)]
|
||||
class Required implements ValidatorInterface
|
||||
{
|
||||
|
||||
|
||||
public function dispatch(string $name): bool
|
||||
/**
|
||||
* @param object $class
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public function dispatch(object $class, string $name): bool
|
||||
{
|
||||
// TODO: Implement dispatch() method.
|
||||
return true;
|
||||
return $class->$name === null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Inject\Validator\Inject;
|
||||
namespace Kiri\Router\Validator\Inject;
|
||||
|
||||
use Kiri\Router\Interface\ValidatorInterface;
|
||||
|
||||
#[\Attribute(\Attribute::TARGET_PROPERTY)]
|
||||
class Round implements ValidatorInterface
|
||||
@@ -17,12 +18,13 @@ class Round implements ValidatorInterface
|
||||
|
||||
|
||||
/**
|
||||
* @param object $class
|
||||
* @param string $name
|
||||
* @return bool
|
||||
*/
|
||||
public function dispatch(string $name): bool
|
||||
public function dispatch(object $class, string $name): bool
|
||||
{
|
||||
// TODO: Implement dispatch() method.
|
||||
return round($name, $this->value) == $name;
|
||||
return round($class->$name, $this->value) === $class->$name;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Kiri\Inject\Validator;
|
||||
namespace Kiri\Router\Validator;
|
||||
|
||||
use Kiri\Inject\Validator\Inject\ValidatorInterface;
|
||||
use Kiri\Router\Interface\ValidatorInterface;
|
||||
use Kiri\Router\ServerRequest;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
|
||||
class Validator
|
||||
{
|
||||
@@ -17,14 +19,39 @@ class Validator
|
||||
private string $message;
|
||||
|
||||
|
||||
private object $formData;
|
||||
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param object $data
|
||||
* @param ValidatorInterface $rule
|
||||
* @return void
|
||||
*/
|
||||
public function addRule(string $name, ValidatorInterface $rule): void
|
||||
public function addRule(string $name, object $data, ValidatorInterface $rule): void
|
||||
{
|
||||
$this->rules[$name] = $rule;
|
||||
$this->formData = $data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param ServerRequestInterface|ServerRequest $request
|
||||
* @return Validator
|
||||
*/
|
||||
public function bindData(ServerRequestInterface|ServerRequest $request): static
|
||||
{
|
||||
if ($request->isPost) {
|
||||
$data = $request->getParsedBody();
|
||||
} else {
|
||||
$data = $request->getQueryParams();
|
||||
}
|
||||
foreach ($data as $key => $value) {
|
||||
if (method_exists($this->formData, $key)) {
|
||||
$this->formData->{$key} = $value;
|
||||
}
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +61,7 @@ class Validator
|
||||
public function run(): bool
|
||||
{
|
||||
foreach ($this->rules as $name => $rule) {
|
||||
if (!$rule->dispatch($name)) {
|
||||
if (!$rule->dispatch($this->formData, $name)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,41 @@
|
||||
|
||||
namespace Kiri\Router\Validator;
|
||||
|
||||
class ValidatorMiddleware
|
||||
use Kiri\Di\Context;
|
||||
use Kiri\Router\Constrict\Stream;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Server\MiddlewareInterface;
|
||||
use Psr\Http\Server\RequestHandlerInterface;
|
||||
|
||||
class ValidatorMiddleware implements MiddlewareInterface
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param Validator $validator
|
||||
*/
|
||||
public function __construct(readonly public Validator $validator)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param ServerRequestInterface $request
|
||||
* @param RequestHandlerInterface $handler
|
||||
* @return ResponseInterface
|
||||
*/
|
||||
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
|
||||
{
|
||||
try {
|
||||
$this->validator->bindData($request);
|
||||
return $handler->handle($request);
|
||||
} catch (\Throwable $throwable) {
|
||||
/** @var ResponseInterface $response */
|
||||
$response = Context::get(ResponseInterface::class);
|
||||
$response->withStatus(407)->withBody(new Stream($throwable->getMessage()));
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user