111
This commit is contained in:
@@ -70,8 +70,7 @@ class Node
|
||||
|
||||
|
||||
/**
|
||||
* @throws NotFindClassException
|
||||
* @throws ReflectionException
|
||||
* @param \Http\Route\Router $router
|
||||
*/
|
||||
public function __construct(public Router $router)
|
||||
{
|
||||
@@ -197,7 +196,7 @@ class Node
|
||||
* @param RequestInterface $request
|
||||
* @return bool
|
||||
*/
|
||||
#[Pure] public function methodAllow(RequestInterface $request): bool
|
||||
public function methodAllow(RequestInterface $request): bool
|
||||
{
|
||||
if (!in_array($request->getMethod(), $this->method)) {
|
||||
return true;
|
||||
|
||||
@@ -15,6 +15,7 @@ use Kiri\Abstracts\Config;
|
||||
use Kiri\Exception\ConfigException;
|
||||
use Kiri\Exception\NotFindClassException;
|
||||
use Kiri\Kiri;
|
||||
use Psr\Http\Message\UriInterface;
|
||||
use ReflectionException;
|
||||
use Server\Constrict\RequestInterface;
|
||||
use Throwable;
|
||||
@@ -28,7 +29,7 @@ defined('ROUTER_HASH') or define('ROUTER_HASH', 2);
|
||||
*/
|
||||
class Router extends HttpService implements RouterInterface
|
||||
{
|
||||
/** @var Node[] $nodes */
|
||||
/** @var \Http\Route\Node[] $nodes */
|
||||
public array $nodes = [];
|
||||
public array $groupTacks = [];
|
||||
public ?string $namespace = 'App\\Http\\Controllers';
|
||||
@@ -133,15 +134,12 @@ class Router extends HttpService implements RouterInterface
|
||||
*/
|
||||
private function tree($path, $handler, string $method = 'any'): Node
|
||||
{
|
||||
$explode = $this->split($path);
|
||||
$start = array_shift($explode);
|
||||
$parent = $this->nodes[$start] ?? null;
|
||||
if (is_null($parent)) {
|
||||
$parent = $this->nodes[$start] = $this->NodeInstance($start, 0, $method);
|
||||
}
|
||||
[$parent, $explode] = $this->getRootNode($path, $method);
|
||||
|
||||
if (!empty($explode)) {
|
||||
$parent = $this->bindNode($parent, $explode, $method);
|
||||
}
|
||||
|
||||
if (!in_array($method, $parent->method)) {
|
||||
$parent->method[] = $method;
|
||||
}
|
||||
@@ -149,6 +147,31 @@ class Router extends HttpService implements RouterInterface
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $root
|
||||
* @param $method
|
||||
* @param bool $create
|
||||
* @return array<\Http\Route\Node, array>
|
||||
*/
|
||||
private function getRootNode($root, $method, bool $create = true): array
|
||||
{
|
||||
[$start, $explode] = $this->path_recombination($root);
|
||||
|
||||
foreach ($this->nodes as $node) {
|
||||
if ($node->path == $start) {
|
||||
return [$node, $explode];
|
||||
}
|
||||
}
|
||||
if ($create) {
|
||||
$parent = $this->NodeInstance($root, 0, $method);
|
||||
$this->nodes[] = $parent;
|
||||
|
||||
return [$parent, $explode];
|
||||
}
|
||||
return [null, null];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Node $parent
|
||||
* @param array $explode
|
||||
@@ -401,8 +424,13 @@ class Router extends HttpService implements RouterInterface
|
||||
*/
|
||||
public function tree_search(?array $explode): ?Node
|
||||
{
|
||||
$parent = $this->nodes[array_shift($explode)] ?? null;
|
||||
if (is_null($parent)) {
|
||||
$start = array_shift($explode);
|
||||
foreach ($this->nodes as $node) {
|
||||
if ($node->path == $start) {
|
||||
$parent = $node;
|
||||
}
|
||||
}
|
||||
if (!isset($parent)) {
|
||||
return null;
|
||||
}
|
||||
while ($value = array_shift($explode)) {
|
||||
@@ -419,17 +447,17 @@ class Router extends HttpService implements RouterInterface
|
||||
* @param $path
|
||||
* @return array|null
|
||||
*/
|
||||
public function split($path): ?array
|
||||
public function path_recombination($path): ?array
|
||||
{
|
||||
$path = $this->addPrefix() . '/' . ltrim($path, '/');
|
||||
if ($path === '/') {
|
||||
return ['/'];
|
||||
return ['/', null];
|
||||
}
|
||||
$filter = array_filter(explode('/', $path));
|
||||
if (!empty($filter)) {
|
||||
return $filter;
|
||||
return [array_shift($filter), $filter];
|
||||
}
|
||||
return ['/'];
|
||||
return ['/', null];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -475,44 +503,27 @@ class Router extends HttpService implements RouterInterface
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $uri
|
||||
* @param $method
|
||||
* @return Node|null
|
||||
*/
|
||||
public function search($uri, $method): Node|null
|
||||
{
|
||||
if (!isset($this->nodes[$method])) {
|
||||
return null;
|
||||
}
|
||||
$methods = $this->nodes[$method];
|
||||
if (isset($methods[$uri])) {
|
||||
return $methods[$uri];
|
||||
}
|
||||
return $methods['/'] ?? null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param RequestInterface $request
|
||||
* @return Node|null
|
||||
* 树杈搜索
|
||||
* @throws Exception
|
||||
*/
|
||||
public function Branch_search(RequestInterface $request): ?Node
|
||||
public function radix_tree(RequestInterface $request): ?Node
|
||||
{
|
||||
$uri = $request->getUri();
|
||||
if ($request->isMethod('OPTIONS')) {
|
||||
$node = $this->tree_search(['*']);
|
||||
[$parent, $explode] = $this->getRootNode($request->getUri()->getPath(),
|
||||
$request->getMethod(), false);
|
||||
if ($parent && !empty($explode)) {
|
||||
/** @var \Http\Route\Node $parent */
|
||||
foreach ($explode as $value) {
|
||||
$node = $parent->findNode($value);
|
||||
if (!$node) {
|
||||
return null;
|
||||
}
|
||||
if (!isset($node)) {
|
||||
$_explode = array_filter(explode('/', $uri->getPath()));
|
||||
if (empty($_explode)) {
|
||||
$_explode = ['/'];
|
||||
$parent = $node;
|
||||
}
|
||||
$node = $this->tree_search($_explode);
|
||||
}
|
||||
return $node;
|
||||
return $parent;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace Protocol\Message;
|
||||
|
||||
use JetBrains\PhpStorm\Pure;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
|
||||
|
||||
@@ -31,7 +31,6 @@ trait Message
|
||||
protected array $headers = [];
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @var array|null
|
||||
*/
|
||||
@@ -90,22 +89,64 @@ trait Message
|
||||
|
||||
|
||||
/**
|
||||
* @param \Swoole\Http\Request $request
|
||||
* @return static
|
||||
* @return array
|
||||
*/
|
||||
public function parseRequestHeaders(\Swoole\Http\Request $request): static
|
||||
public function parse_curl_header(): array
|
||||
{
|
||||
$index = strpos($request->getData(), "\r\n\r\n");
|
||||
$headers = explode("\r\n", substr($request->getData(), 0, $index));
|
||||
array_shift($headers);
|
||||
$_headers = [];
|
||||
foreach ($this->headers as $key => $val) {
|
||||
$_headers[] = $key . ': ' . implode(';', $val);
|
||||
}
|
||||
return $_headers;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function withData(string $headerString): static
|
||||
{
|
||||
[$headers, $body] = explode("\r\n\r\n", $headerString);
|
||||
|
||||
$this->stream = new Stream($body);
|
||||
|
||||
return $this->slip_headers($headers);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $headers
|
||||
* @return $this
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function slip_headers($headers): static
|
||||
{
|
||||
$headers = explode("\r\n", $headers);
|
||||
|
||||
$this->resolve_status(array_shift($headers));
|
||||
|
||||
foreach ($headers as $header) {
|
||||
[$key, $value] = explode(': ', $header);
|
||||
$this->addRequestHeader($key, $value);
|
||||
$this->withHeader($key, $value);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $protocol
|
||||
*/
|
||||
private function resolve_status(string $protocol)
|
||||
{
|
||||
if ($this instanceof ResponseInterface) {
|
||||
[$sch, $status, $message] = explode(' ', $protocol);
|
||||
[$sch, $protocolVersion] = explode('/', $sch);
|
||||
$this->withProtocolVersion($protocolVersion)
|
||||
->withStatus(intval($status));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
* @param $value
|
||||
@@ -245,4 +286,10 @@ trait Message
|
||||
return $this->getHeaderLine('Access-Control-Request-Method');
|
||||
}
|
||||
|
||||
|
||||
protected function setStore($key, callable $callback)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ use Psr\Http\Message\UriInterface;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
abstract class Request implements RequestInterface
|
||||
class Request implements RequestInterface
|
||||
{
|
||||
|
||||
use Message;
|
||||
|
||||
@@ -14,6 +14,9 @@ class ServerRequest extends Request implements ServerRequestInterface
|
||||
{
|
||||
|
||||
|
||||
const PARSE_BODY = 'with.parsed.body.callback';
|
||||
|
||||
|
||||
/**
|
||||
* @var mixed
|
||||
*/
|
||||
@@ -64,29 +67,21 @@ class ServerRequest extends Request implements ServerRequestInterface
|
||||
/**
|
||||
* @param \Swoole\Http\Request $request
|
||||
* @return static|ServerRequestInterface
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function createServerRequest(\Swoole\Http\Request $request): static|ServerRequestInterface
|
||||
{
|
||||
return (new static())->parseRequestHeaders($request)
|
||||
->withServerParams($request->server)
|
||||
->withServerTarget($request)
|
||||
->withCookieParams($request->cookie)
|
||||
->withUri(Uri::parseUri($request))
|
||||
->withBody(new Stream($request->getContent()))
|
||||
->withQueryParams($request->get ?? [])
|
||||
->withUploadedFiles($request->files ?? [])
|
||||
->withMethod($request->getMethod())
|
||||
->withParsedBody(function (StreamInterface $stream, ?array $posts) {
|
||||
try {
|
||||
$content = Parse::data($stream->getContents());
|
||||
if (!empty($content)) {
|
||||
return $content;
|
||||
}
|
||||
return $posts;
|
||||
} catch (\Throwable $throwable) {
|
||||
return $posts;
|
||||
}
|
||||
});
|
||||
$serverRequest = new ServerRequest();
|
||||
$serverRequest->withData($request->getData());
|
||||
$serverRequest->withServerParams($request->server);
|
||||
$serverRequest->withServerTarget($request);
|
||||
$serverRequest->withCookieParams($request->cookie);
|
||||
$serverRequest->withUri(Uri::parseUri($request));
|
||||
$serverRequest->withQueryParams($request->get ?? []);
|
||||
$serverRequest->withUploadedFiles($request->files ?? []);
|
||||
$serverRequest->withMethod($request->getMethod());
|
||||
$serverRequest->withParsedBody($request->post);
|
||||
return $serverRequest;
|
||||
}
|
||||
|
||||
|
||||
@@ -145,7 +140,7 @@ class ServerRequest extends Request implements ServerRequestInterface
|
||||
public function getParsedBody(): object|array|null
|
||||
{
|
||||
if (empty($this->parsedBody)) {
|
||||
$callback = Context::getContext('with.parsed.body.callback');
|
||||
$callback = Context::getContext(self::PARSE_BODY);
|
||||
|
||||
$this->parsedBody = $callback($this->getBody(), $this->serverTarget->post);
|
||||
}
|
||||
@@ -159,7 +154,14 @@ class ServerRequest extends Request implements ServerRequestInterface
|
||||
*/
|
||||
public function withParsedBody($data): ServerRequestInterface
|
||||
{
|
||||
Context::setContext('with.parsed.body.callback', $data);
|
||||
$functions = function (StreamInterface $stream) use ($data) {
|
||||
$content = Parse::data($stream->getContents());
|
||||
if (!empty($content)) {
|
||||
return $content;
|
||||
}
|
||||
return $data;
|
||||
};
|
||||
Context::setContext(self::PARSE_BODY, $functions);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
@@ -54,6 +54,7 @@ class Uri implements UriInterface
|
||||
return $this->host;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return int|null
|
||||
*/
|
||||
|
||||
@@ -52,6 +52,7 @@ class Request implements RequestInterface
|
||||
/**
|
||||
* @param \Swoole\Http\Request $request
|
||||
* @return Request
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function create(\Swoole\Http\Request $request): Request
|
||||
{
|
||||
|
||||
@@ -42,7 +42,7 @@ class Http extends \Server\Abstracts\Http implements OnClose, OnConnect
|
||||
public function onRequest(Request $request, Response $response): void
|
||||
{
|
||||
try {
|
||||
$node = $this->router->Branch_search($Psr7Request = ScRequest::create($request));
|
||||
$node = $this->router->radix_tree($Psr7Request = ScRequest::create($request));
|
||||
if (!($node instanceof Node)) {
|
||||
throw new RequestException(Constant::STATUS_404_MESSAGE, 404);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user