Allow the extra path to be ignored when redirecting

This commit is contained in:
Alejandro Celaya
2024-12-01 09:51:00 +01:00
parent e74ee793a0
commit c65349d265
7 changed files with 68 additions and 18 deletions

View File

@@ -84,7 +84,7 @@ enum EnvVars: string
case IS_HTTPS_ENABLED = 'IS_HTTPS_ENABLED';
case DEFAULT_DOMAIN = 'DEFAULT_DOMAIN';
case AUTO_RESOLVE_TITLES = 'AUTO_RESOLVE_TITLES';
case REDIRECT_APPEND_EXTRA_PATH = 'REDIRECT_APPEND_EXTRA_PATH';
case REDIRECT_EXTRA_PATH_MODE = 'REDIRECT_EXTRA_PATH_MODE';
case MULTI_SEGMENT_SLUGS_ENABLED = 'MULTI_SEGMENT_SLUGS_ENABLED';
case ROBOTS_ALLOW_ALL_SHORT_URLS = 'ROBOTS_ALLOW_ALL_SHORT_URLS';
case ROBOTS_USER_AGENTS = 'ROBOTS_USER_AGENTS';
@@ -92,6 +92,8 @@ enum EnvVars: string
case MEMORY_LIMIT = 'MEMORY_LIMIT';
case INITIAL_API_KEY = 'INITIAL_API_KEY';
case SKIP_INITIAL_GEOLITE_DOWNLOAD = 'SKIP_INITIAL_GEOLITE_DOWNLOAD';
/** @deprecated Use REDIRECT_EXTRA_PATH */
case REDIRECT_APPEND_EXTRA_PATH = 'REDIRECT_APPEND_EXTRA_PATH';
public function loadFromEnv(): mixed
{
@@ -125,11 +127,13 @@ enum EnvVars: string
self::DEFAULT_SHORT_CODES_LENGTH => DEFAULT_SHORT_CODES_LENGTH,
self::SHORT_URL_MODE => ShortUrlMode::STRICT->value,
self::IS_HTTPS_ENABLED, self::AUTO_RESOLVE_TITLES => true,
self::REDIRECT_APPEND_EXTRA_PATH,
self::MULTI_SEGMENT_SLUGS_ENABLED,
self::SHORT_URL_TRAILING_SLASH => false,
self::DEFAULT_DOMAIN, self::BASE_PATH => '',
self::CACHE_NAMESPACE => 'Shlink',
// Deprecated. In Shlink 5.0.0, add default value for REDIRECT_EXTRA_PATH_MODE
self::REDIRECT_APPEND_EXTRA_PATH => false,
// self::REDIRECT_EXTRA_PATH_MODE => ExtraPathMode::DEFAULT->value,
self::REDIS_PUB_SUB_ENABLED,
self::MATOMO_ENABLED,

View File

@@ -0,0 +1,13 @@
<?php
namespace Shlinkio\Shlink\Core\Config\Options;
enum ExtraPathMode: string
{
/** URLs with extra path will not match a short URL */
case DEFAULT = 'default';
/** The extra path will be appended to the long URL */
case APPEND = 'append';
/** The extra path will be ignored */
case IGNORE = 'ignore';
}

View File

@@ -22,10 +22,10 @@ final readonly class UrlShortenerOptions
public string $schema = 'http',
public int $defaultShortCodesLength = DEFAULT_SHORT_CODES_LENGTH,
public bool $autoResolveTitles = false,
public bool $appendExtraPath = false,
public bool $multiSegmentSlugsEnabled = false,
public bool $trailingSlashEnabled = false,
public ShortUrlMode $mode = ShortUrlMode::STRICT,
public ExtraPathMode $extraPathMode = ExtraPathMode::DEFAULT,
) {
}
@@ -35,17 +35,26 @@ final readonly class UrlShortenerOptions
(int) EnvVars::DEFAULT_SHORT_CODES_LENGTH->loadFromEnv(),
MIN_SHORT_CODES_LENGTH,
);
$mode = EnvVars::SHORT_URL_MODE->loadFromEnv();
// Deprecated. Initialize extra path from REDIRECT_APPEND_EXTRA_PATH.
$appendExtraPath = EnvVars::REDIRECT_APPEND_EXTRA_PATH->loadFromEnv();
$extraPathMode = $appendExtraPath ? ExtraPathMode::APPEND : ExtraPathMode::DEFAULT;
// If REDIRECT_EXTRA_PATH_MODE was explicitly provided, it has precedence
$extraPathModeFromEnv = EnvVars::REDIRECT_EXTRA_PATH_MODE->loadFromEnv();
if ($extraPathModeFromEnv !== null) {
$extraPathMode = ExtraPathMode::tryFrom($extraPathModeFromEnv) ?? ExtraPathMode::DEFAULT;
}
return new self(
defaultDomain: EnvVars::DEFAULT_DOMAIN->loadFromEnv(),
schema: ((bool) EnvVars::IS_HTTPS_ENABLED->loadFromEnv()) ? 'https' : 'http',
defaultShortCodesLength: $shortCodesLength,
autoResolveTitles: (bool) EnvVars::AUTO_RESOLVE_TITLES->loadFromEnv(),
appendExtraPath: (bool) EnvVars::REDIRECT_APPEND_EXTRA_PATH->loadFromEnv(),
multiSegmentSlugsEnabled: (bool) EnvVars::MULTI_SEGMENT_SLUGS_ENABLED->loadFromEnv(),
trailingSlashEnabled: (bool) EnvVars::SHORT_URL_TRAILING_SLASH->loadFromEnv(),
mode: ShortUrlMode::tryFrom($mode) ?? ShortUrlMode::STRICT,
mode: ShortUrlMode::tryFrom(EnvVars::SHORT_URL_MODE->loadFromEnv()) ?? ShortUrlMode::STRICT,
extraPathMode: $extraPathMode,
);
}

View File

@@ -9,6 +9,7 @@ use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\UriInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Shlinkio\Shlink\Core\Config\Options\ExtraPathMode;
use Shlinkio\Shlink\Core\Config\Options\UrlShortenerOptions;
use Shlinkio\Shlink\Core\ErrorHandler\Model\NotFoundType;
use Shlinkio\Shlink\Core\Exception\ShortUrlNotFoundException;
@@ -51,7 +52,7 @@ readonly class ExtraPathRedirectMiddleware implements MiddlewareInterface
private function shouldApplyLogic(NotFoundType|null $notFoundType): bool
{
if ($notFoundType === null || ! $this->urlShortenerOptions->appendExtraPath) {
if ($notFoundType === null || $this->urlShortenerOptions->extraPathMode === ExtraPathMode::DEFAULT) {
return false;
}
@@ -75,7 +76,11 @@ readonly class ExtraPathRedirectMiddleware implements MiddlewareInterface
try {
$shortUrl = $this->resolver->resolveEnabledShortUrl($identifier);
$longUrl = $this->redirectionBuilder->buildShortUrlRedirect($shortUrl, $request, $extraPath);
$longUrl = $this->redirectionBuilder->buildShortUrlRedirect(
$shortUrl,
$request,
$this->urlShortenerOptions->extraPathMode === ExtraPathMode::APPEND ? $extraPath : null,
);
$this->requestTracker->trackIfApplicable(
$shortUrl,
$request->withAttribute(REDIRECT_URL_REQUEST_ATTRIBUTE, $longUrl),