This commit is contained in:
as2252258@163.com
2021-09-12 03:46:24 +08:00
parent 989158bc3d
commit b91199671a
8 changed files with 1151 additions and 1090 deletions
+2 -3
View File
@@ -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;
+52 -41
View File
@@ -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;
}
+56 -9
View File
@@ -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)
{
}
}
+1 -1
View File
@@ -11,7 +11,7 @@ use Psr\Http\Message\UriInterface;
/**
*
*/
abstract class Request implements RequestInterface
class Request implements RequestInterface
{
use Message;
+24 -22
View File
@@ -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;
}
+1
View File
@@ -54,6 +54,7 @@ class Uri implements UriInterface
return $this->host;
}
/**
* @return int|null
*/
+1
View File
@@ -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
{
+1 -1
View File
@@ -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);
}