Open ghostwriter opened 2 weeks ago
<?php
declare(strict_types=1);
namespace Ghostwriter\Router\Interface;
use Closure;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
interface RouteCollectorInterface
{
public function add(RouteInterface $route): void;
/**
* @param non-empty-string $path
* @param class-string<RequestHandlerInterface> $handler
* @param non-empty-string $name
* @param list<class-string<MiddlewareInterface>> $middlewares
*/
public function any(string $path, string $handler, string $name, array $middlewares = []): self;
/**
* @param non-empty-string $path
* @param class-string<RequestHandlerInterface> $handler
* @param non-empty-string $name
* @param list<class-string<MiddlewareInterface>> $middlewares
*/
public function delete(string $path, string $handler, string $name, array $middlewares = []): self;
/**
* @param non-empty-string $name
* @param Closure(RouteCollectorInterface): void $callback
*/
public function domain(string $name, Closure $callback): self;
/**
* @param non-empty-string $path
* @param class-string<RequestHandlerInterface> $handler
* @param non-empty-string $name
* @param list<class-string<MiddlewareInterface>> $middlewares
*/
public function get(string $path, string $handler, string $name, array $middlewares = []): self;
/**
* @param non-empty-string $path
* @param class-string<RequestHandlerInterface> $handler
* @param non-empty-string $name
* @param list<class-string<MiddlewareInterface>> $middlewares
*/
public function head(string $path, string $handler, string $name, array $middlewares = []): self;
/**
* @param list<class-string<MiddlewareInterface>> $middlewares
* @param Closure(RouteCollectorInterface): void $callback
*/
public function middleware(array $middlewares, Closure $callback): self;
/**
* @param non-empty-string $name
* @param Closure(RouteCollectorInterface): void $callback
*/
public function name(string $name, Closure $callback): self;
/**
* @param non-empty-string $method
* @param non-empty-string $path
* @param class-string<RequestHandlerInterface> $handler
* @param non-empty-string $name
* @param list<class-string<MiddlewareInterface>> $middlewares
*/
public function map(
string $method,
string $path,
string $handler,
string $name,
array $middlewares = [],
): self;
/**
* @param non-empty-string $path
* @param class-string<RequestHandlerInterface> $handler
* @param non-empty-string $name
* @param list<class-string<MiddlewareInterface>> $middlewares
*/
public function options(string $path, string $handler, string $name, array $middlewares = []): self;
/**
* @param non-empty-string $path
* @param class-string<RequestHandlerInterface> $handler
* @param non-empty-string $name
* @param list<class-string<MiddlewareInterface>> $middlewares
*/
public function patch(string $path, string $handler, string $name, array $middlewares = []): self;
/**
* @param non-empty-string $path
* @param class-string<RequestHandlerInterface> $handler
* @param non-empty-string $name
* @param list<class-string<MiddlewareInterface>> $middlewares
*/
public function post(string $path, string $handler, string $name, array $middlewares = []): self;
/**
* @param non-empty-string $path
* @param Closure(RouteCollectorInterface):void $callback
*/
public function prefix(string $path, Closure $callback): self;
/**
* @param non-empty-string $path
* @param class-string<RequestHandlerInterface> $handler
* @param non-empty-string $name
* @param list<class-string<MiddlewareInterface>> $middlewares
*/
public function put(string $path, string $handler, string $name, array $middlewares = []): self;
/**
* @return array<non-empty-string,RouteInterface>
*/
public function routes(): array;
}
<?php
declare(strict_types=1);
namespace Ghostwriter\Router\Interface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
interface RouteInterface
{
/** @return non-empty-string */
public function domain(): string;
/** @return class-string<RequestHandlerInterface> */
public function handler(): string;
/** @return non-empty-string */
public function method(): string;
/** @return list<class-string<MiddlewareInterface>> */
public function middlewares(): array;
/** @return non-empty-string */
public function name(): string;
/** @return non-empty-string */
public function path(): string;
}
<?php
declare(strict_types=1);
namespace Ghostwriter\Router\Interface;
use Ghostwriter\Router\Interface\Exception\RouteMethodNotAllowedExceptionInterface;
use Ghostwriter\Router\Interface\Exception\RouteNotFoundExceptionInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\UriInterface;
interface RouterInterface
{
public function add(RouteInterface $route): void;
/**
* @throws RouteNotFoundExceptionInterface
* @throws RouteMethodNotAllowedExceptionInterface
*/
public function match(ServerRequestInterface $serverRequest): RouteInterface;
/**
* @return array<non-empty-string,RouteInterface>
*/
public function routes(): array;
/**
* Generate a URI from a named route.
*
* $router->add(Route::new('GET', '/post/{id}', 'PostHandler::class', 'post.show', ['AuthMiddleware::class'], 'localhost'))
*
* $router->uri('post.show', ['id' => 1], ['page' => 2], 'comments') => /post/1?page=2#comments
*
* @param array<string,scalar> $parameters
* @param array<string,scalar> $query
*
* @throws RouteNotFoundExceptionInterface
*/
public function uri(
string $name,
array $parameters = [],
array $query = [],
string $fragment = ''
): UriInterface;
}
final readonly class MethodOverrideMiddleware implements MiddlewareInterface
{
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
foreach (['X-HTTP-Method-Override', 'X-Method-Override', 'X-HTTP-Method', 'X-Method'] as $header) {
if (! $request->hasHeader($header)) {
continue;
}
return $handler->handle($request->withMethod(mb_strtoupper($request->getHeaderLine($header))));
}
$method = $request->getMethod();
if ($method === 'POST') {
$parsedBody = $request->getParsedBody();
$method = $parsedBody['_method'] ?? $parsedBody['__METHOD__'] ?? $method;
}
// Continue processing with the updated request
return $handler->handle($request->withMethod($method));
}
}
Segment: A portion of a URL path that can contain dynamic or static content.
For example, in the URL
https://{app}.example.com/users/{userId}/profile/{section}
,{app}
,/users
and/profile
are segments.The segment
{app}
represents a dynamic part of the URL that can change based on user input.Parameter: A variable in the URL that can represent different values.
Parameters can be used within segments to capture dynamic values or provide additional information.
For example, in the URL
/search?q={query}
,q
is a query parameter that can be replaced with different search terms./users/{userId}
{userId}
./products/{productId:[0-9]+}
{productId:[0-9]+}
./files/{path:*}
{path*}
./posts/{postId?}
{postId?}
./search?q={query}
?q={query}
./items;color={color};size={size}
;color={color};size={size}
./static/about
/static/about
./users/{id}/profile/{section}
/users/{id}/profile/{section}
.{tenant}.example.com
{tenant}.example.com
./flights/{from}-{to}
/flights/{from}-{to}
./files/{category}.{filename}
/files/{category}.{filename}
.