Take redirect rules into consideration when resolving the long URL for a short URL

This commit is contained in:
Alejandro Celaya committed 2024-02-25 12:34:27 +01:00
1 parent 7f83d37b3c
commit 4e87affb0b
2 files changed
+26 -2

No files matched your search

@@ -4,9 +4,12 @@ namespace Shlinkio\Shlink\Core\RedirectRule\Entity;
use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection; use Doctrine\Common\Collections\Collection;
use Psr\Http\Message\ServerRequestInterface;
use Shlinkio\Shlink\Common\Entity\AbstractEntity; use Shlinkio\Shlink\Common\Entity\AbstractEntity;
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl; use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
use function Shlinkio\Shlink\Core\ArrayUtils\every;
class ShortUrlRedirectRule extends AbstractEntity class ShortUrlRedirectRule extends AbstractEntity
{ {
/** /**
@@ -14,9 +17,20 @@ class ShortUrlRedirectRule extends AbstractEntity
*/ */
public function __construct( public function __construct(
private readonly ShortUrl $shortUrl, // No need to read this field. It's used by doctrine private readonly ShortUrl $shortUrl, // No need to read this field. It's used by doctrine
public readonly int $priority, private readonly int $priority,
public readonly string $longUrl, public readonly string $longUrl,
public readonly Collection $conditions = new ArrayCollection(), public readonly Collection $conditions = new ArrayCollection(),
) { ) {
} }
/**
* Tells if this condition matches provided request
*/
public function matchesRequest(ServerRequestInterface $request): bool
{
return every(
$this->conditions,
static fn (RedirectCondition $condition) => $condition->matchesRequest($request),
);
}
} }
@@ -5,6 +5,7 @@ namespace Shlinkio\Shlink\Core\RedirectRule;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ServerRequestInterface;
use Shlinkio\Shlink\Core\Model\DeviceType; use Shlinkio\Shlink\Core\Model\DeviceType;
use Shlinkio\Shlink\Core\RedirectRule\Entity\ShortUrlRedirectRule;
use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl; use Shlinkio\Shlink\Core\ShortUrl\Entity\ShortUrl;
readonly class ShortUrlRedirectionResolver implements ShortUrlRedirectionResolverInterface readonly class ShortUrlRedirectionResolver implements ShortUrlRedirectionResolverInterface
@@ -15,7 +16,16 @@ readonly class ShortUrlRedirectionResolver implements ShortUrlRedirectionResolve
public function resolveLongUrl(ShortUrl $shortUrl, ServerRequestInterface $request): string public function resolveLongUrl(ShortUrl $shortUrl, ServerRequestInterface $request): string
{ {
// TODO Resolve rules and check if any of them matches $rules = $this->em->getRepository(ShortUrlRedirectRule::class)->findBy(
criteria: ['shortUrl' => $shortUrl],
orderBy: ['priority' => 'ASC'],
);
foreach ($rules as $rule) {
// Return the long URL for the first rule found that matches
if ($rule->matchesRequest($request)) {
return $rule->longUrl;
}
}
$device = DeviceType::matchFromUserAgent($request->getHeaderLine('User-Agent')); $device = DeviceType::matchFromUserAgent($request->getHeaderLine('User-Agent'));
return $shortUrl->longUrlForDevice($device); return $shortUrl->longUrlForDevice($device);