mirror of
https://github.com/shlinkio/shlink.git
synced 2024-12-22 15:13:59 -06:00
Added support for redirect status code 307 and 308
This commit is contained in:
parent
85464f0fbb
commit
390bc59d99
@ -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,
|
||||
),
|
||||
|
@ -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[^>]*>(.*?)<\/title>/i'; // Matches the value inside a html title tag
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
20
module/Core/src/Util/RedirectStatus.php
Normal file
20
module/Core/src/Util/RedirectStatus.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace Shlinkio\Shlink\Core\Util;
|
||||
|
||||
use Fig\Http\Message\StatusCodeInterface;
|
||||
|
||||
use function Functional\contains;
|
||||
|
||||
enum RedirectStatus: int
|
||||
{
|
||||
case STATUS_301 = StatusCodeInterface::STATUS_MOVED_PERMANENTLY;
|
||||
case STATUS_302 = StatusCodeInterface::STATUS_FOUND;
|
||||
case STATUS_307 = StatusCodeInterface::STATUS_TEMPORARY_REDIRECT;
|
||||
case STATUS_308 = StatusCodeInterface::STATUS_PERMANENT_REDIRECT;
|
||||
|
||||
public function allowsCache(): bool
|
||||
{
|
||||
return contains([self::STATUS_301, self::STATUS_308], $this);
|
||||
}
|
||||
}
|
@ -36,11 +36,15 @@ class RedirectResponseHelperTest extends TestCase
|
||||
public function provideRedirectConfigs(): iterable
|
||||
{
|
||||
yield 'status 302' => [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
|
||||
|
Loading…
Reference in New Issue
Block a user