diff --git a/config/autoload/redirects.global.php b/config/autoload/redirects.global.php
index 426bb2ac..26a3c032 100644
--- a/config/autoload/redirects.global.php
+++ b/config/autoload/redirects.global.php
@@ -16,7 +16,7 @@ return [
],
'redirects' => [
- 'redirect_status_code' => (int) EnvVars::REDIRECT_STATUS_CODE->loadFromEnv(DEFAULT_REDIRECT_STATUS_CODE),
+ 'redirect_status_code' => (int) EnvVars::REDIRECT_STATUS_CODE->loadFromEnv(DEFAULT_REDIRECT_STATUS_CODE->value),
'redirect_cache_lifetime' => (int) EnvVars::REDIRECT_CACHE_LIFETIME->loadFromEnv(
DEFAULT_REDIRECT_CACHE_LIFETIME,
),
diff --git a/config/constants.php b/config/constants.php
index d3d869c3..f6d5e9aa 100644
--- a/config/constants.php
+++ b/config/constants.php
@@ -4,12 +4,12 @@ declare(strict_types=1);
namespace Shlinkio\Shlink;
-use Fig\Http\Message\StatusCodeInterface;
+use Shlinkio\Shlink\Core\Util\RedirectStatus;
const DEFAULT_DELETE_SHORT_URL_THRESHOLD = 15;
const DEFAULT_SHORT_CODES_LENGTH = 5;
const MIN_SHORT_CODES_LENGTH = 4;
-const DEFAULT_REDIRECT_STATUS_CODE = StatusCodeInterface::STATUS_FOUND;
+const DEFAULT_REDIRECT_STATUS_CODE = RedirectStatus::STATUS_302;
const DEFAULT_REDIRECT_CACHE_LIFETIME = 30;
const LOCAL_LOCK_FACTORY = 'Shlinkio\Shlink\LocalLockFactory';
const TITLE_TAG_VALUE = '/
]*>(.*?)<\/title>/i'; // Matches the value inside a html title tag
diff --git a/module/Core/src/Options/RedirectOptions.php b/module/Core/src/Options/RedirectOptions.php
index 9a1fedac..dd9f0a6d 100644
--- a/module/Core/src/Options/RedirectOptions.php
+++ b/module/Core/src/Options/RedirectOptions.php
@@ -4,23 +4,22 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\Core\Options;
-use function Functional\contains;
+use Fig\Http\Message\StatusCodeInterface;
+use Shlinkio\Shlink\Core\Util\RedirectStatus;
use const Shlinkio\Shlink\DEFAULT_REDIRECT_CACHE_LIFETIME;
use const Shlinkio\Shlink\DEFAULT_REDIRECT_STATUS_CODE;
final class RedirectOptions
{
- public readonly int $redirectStatusCode;
+ public readonly RedirectStatus $redirectStatusCode;
public readonly int $redirectCacheLifetime;
public function __construct(
- int $redirectStatusCode = DEFAULT_REDIRECT_STATUS_CODE,
+ int $redirectStatusCode = StatusCodeInterface::STATUS_FOUND,
int $redirectCacheLifetime = DEFAULT_REDIRECT_CACHE_LIFETIME,
) {
- $this->redirectStatusCode = contains([301, 302], $redirectStatusCode)
- ? $redirectStatusCode
- : DEFAULT_REDIRECT_STATUS_CODE;
+ $this->redirectStatusCode = RedirectStatus::tryFrom($redirectStatusCode) ?? DEFAULT_REDIRECT_STATUS_CODE;
$this->redirectCacheLifetime = $redirectCacheLifetime > 0
? $redirectCacheLifetime
: DEFAULT_REDIRECT_CACHE_LIFETIME;
diff --git a/module/Core/src/Util/RedirectResponseHelper.php b/module/Core/src/Util/RedirectResponseHelper.php
index dfc87480..01e581a7 100644
--- a/module/Core/src/Util/RedirectResponseHelper.php
+++ b/module/Core/src/Util/RedirectResponseHelper.php
@@ -4,7 +4,6 @@ declare(strict_types=1);
namespace Shlinkio\Shlink\Core\Util;
-use Fig\Http\Message\StatusCodeInterface;
use Laminas\Diactoros\Response\RedirectResponse;
use Psr\Http\Message\ResponseInterface;
use Shlinkio\Shlink\Core\Options\RedirectOptions;
@@ -13,17 +12,17 @@ use function sprintf;
class RedirectResponseHelper implements RedirectResponseHelperInterface
{
- public function __construct(private RedirectOptions $options)
+ public function __construct(private readonly RedirectOptions $options)
{
}
public function buildRedirectResponse(string $location): ResponseInterface
{
$statusCode = $this->options->redirectStatusCode;
- $headers = $statusCode === StatusCodeInterface::STATUS_FOUND ? [] : [
+ $headers = ! $statusCode->allowsCache() ? [] : [
'Cache-Control' => sprintf('private,max-age=%s', $this->options->redirectCacheLifetime),
];
- return new RedirectResponse($location, $statusCode, $headers);
+ return new RedirectResponse($location, $statusCode->value, $headers);
}
}
diff --git a/module/Core/src/Util/RedirectStatus.php b/module/Core/src/Util/RedirectStatus.php
new file mode 100644
index 00000000..d14e4fea
--- /dev/null
+++ b/module/Core/src/Util/RedirectStatus.php
@@ -0,0 +1,20 @@
+ [302, 20, 302, null];
- yield 'status over 302' => [400, 20, 302, null];
+ yield 'status 307' => [307, 20, 307, null];
+ yield 'status over 308' => [400, 20, 302, null];
yield 'status below 301' => [201, 20, 302, null];
yield 'status 301 with valid expiration' => [301, 20, 301, 'private,max-age=20'];
yield 'status 301 with zero expiration' => [301, 0, 301, 'private,max-age=30'];
yield 'status 301 with negative expiration' => [301, -20, 301, 'private,max-age=30'];
+ yield 'status 308 with valid expiration' => [308, 20, 308, 'private,max-age=20'];
+ yield 'status 308 with zero expiration' => [308, 0, 308, 'private,max-age=30'];
+ yield 'status 308 with negative expiration' => [308, -20, 308, 'private,max-age=30'];
}
private function helper(?RedirectOptions $options = null): RedirectResponseHelper