Skip to content

Commit

Permalink
Apply middlewares from fallback routes (#643)
Browse files Browse the repository at this point in the history
  • Loading branch information
indykoning authored Nov 20, 2024
1 parent 83b1c3f commit b1d3519
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 11 deletions.
34 changes: 28 additions & 6 deletions src/Http/Controllers/FallbackController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,43 @@
namespace Rapidez\Core\Http\Controllers;

use Exception;
use Illuminate\Container\Container;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Database\RecordsNotFoundException;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
use Illuminate\Routing\Controller;
use Illuminate\Routing\Exceptions\BackedEnumCaseNotFoundException;
use Illuminate\Routing\Pipeline;
use Illuminate\Routing\Route;
use Illuminate\Routing\Router;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Cache;
use Rapidez\Core\Facades\Rapidez;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Exception\RouteNotFoundException;

class FallbackController
class FallbackController extends Controller
{
protected $container;

public function __construct(
?Container $container = null,
protected Router $router
) {
$this->container = $container ?: new Container;
}

public function __invoke(Request $request)
{
$cacheKey = 'fallbackroute-' . md5($request->url());
$route = Cache::get($cacheKey);
if ($route && $response = $this->tryRoute($route)) {
if ($route && $response = $this->tryRoute($route['route'], $request)) {
return $response;
}

foreach (Rapidez::getAllFallbackRoutes() as $route) {
if (! ($response = $this->tryRoute($route))) {
if (! ($response = $this->tryRoute($route['route'], $request))) {
continue;
}

Expand All @@ -41,13 +56,20 @@ public function __invoke(Request $request)
abort(404);
}

protected function tryRoute($route)
protected function tryRoute(Route $route, $request): ?Response
{
try {
$response = App::call($route['action']['uses']);
$middleware = $this->router->gatherRouteMiddleware($route->setContainer($this->container));
/** @var Response $response */
$response = (new Pipeline($this->container))
->send($request)
->through($middleware)
->then(fn ($request) => $this->router->prepareResponse(
$request, $route->bind($request)->run()
));

// Null response is equal to no response or 404.
if ($response === null) {
if (!$response->getContent() || $response->isNotFound()) {
abort(404);
}

Expand Down
27 changes: 22 additions & 5 deletions src/Rapidez.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,51 @@

namespace Rapidez\Core;

use Illuminate\Routing\Route;
use Illuminate\Routing\RouteAction;
use Illuminate\Routing\Router;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Event;
use Rapidez\Core\Models\Store;
use ReflectionClass;

class Rapidez
{
protected string|bool|null $compadreVersion;

public function __construct(protected Collection $routes) {}

public function addFallbackRoute($action, $position = 9999)
public function addFallbackRoute(Route|array|string $action, $position = 9999)
{
$this->routes->push([
'action' => RouteAction::parse('', $action),
'route' => $this->actionToRoute($action)->fallback(),
'position' => $position,
]);

return $this;
}

public function removeFallbackRoute($action)
private function actionToRoute(Route|array|string $action): Route
{
$action = RouteAction::parse('', $action);
$this->routes = $this->routes->reject(fn ($route) => $route['action'] === $action);
if($action instanceof Route)
{
return $action;
}

$router = new ReflectionClass(Router::class);
$createRoute = $router->getMethod('createRoute');
$createRoute->setAccessible(true);

return $createRoute->invoke(app(Router::class), ['GET'], '', $action);
}

public function removeFallbackRoute(Route|array|string $action)
{
$action = $this->actionToRoute($action);
$this->routes = $this->routes->reject(fn ($route) => $route['route']->action === $action->action);

return $this;
}
Expand Down

0 comments on commit b1d3519

Please sign in to comment.