NotFoundRedirectHandler.php 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. <?php
  2. declare(strict_types=1);
  3. namespace Shlinkio\Shlink\Core\ErrorHandler;
  4. use Laminas\Diactoros\Response;
  5. use Mezzio\Router\RouteResult;
  6. use Psr\Http\Message\ResponseInterface;
  7. use Psr\Http\Message\ServerRequestInterface;
  8. use Psr\Http\Message\UriInterface;
  9. use Psr\Http\Server\MiddlewareInterface;
  10. use Psr\Http\Server\RequestHandlerInterface;
  11. use Shlinkio\Shlink\Core\Action\RedirectAction;
  12. use Shlinkio\Shlink\Core\Options\NotFoundRedirectOptions;
  13. use function rtrim;
  14. class NotFoundRedirectHandler implements MiddlewareInterface
  15. {
  16. private NotFoundRedirectOptions $redirectOptions;
  17. private string $shlinkBasePath;
  18. public function __construct(NotFoundRedirectOptions $redirectOptions, string $shlinkBasePath)
  19. {
  20. $this->redirectOptions = $redirectOptions;
  21. $this->shlinkBasePath = $shlinkBasePath;
  22. }
  23. public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
  24. {
  25. /** @var RouteResult $routeResult */
  26. $routeResult = $request->getAttribute(RouteResult::class, RouteResult::fromRouteFailure(null));
  27. $redirectResponse = $this->createRedirectResponse($routeResult, $request->getUri());
  28. return $redirectResponse ?? $handler->handle($request);
  29. }
  30. private function createRedirectResponse(RouteResult $routeResult, UriInterface $uri): ?ResponseInterface
  31. {
  32. $isBaseUrl = rtrim($uri->getPath(), '/') === $this->shlinkBasePath;
  33. if ($isBaseUrl && $this->redirectOptions->hasBaseUrlRedirect()) {
  34. return new Response\RedirectResponse($this->redirectOptions->getBaseUrlRedirect());
  35. }
  36. if (!$isBaseUrl && $routeResult->isFailure() && $this->redirectOptions->hasRegular404Redirect()) {
  37. return new Response\RedirectResponse($this->redirectOptions->getRegular404Redirect());
  38. }
  39. if (
  40. $routeResult->isSuccess() &&
  41. $routeResult->getMatchedRouteName() === RedirectAction::class &&
  42. $this->redirectOptions->hasInvalidShortUrlRedirect()
  43. ) {
  44. return new Response\RedirectResponse($this->redirectOptions->getInvalidShortUrlRedirect());
  45. }
  46. return null;
  47. }
  48. }