Fix ladl.link 404s for QR ecosystem slugs.
Deploy Ladill Link / deploy (push) Successful in 31s

Only direct Link redirects use destination_url; catalog QR slugs proxy through the platform resolver instead of malformed summary URLs.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
isaacclad
2026-06-27 15:26:27 +00:00
co-authored by Cursor
parent db6be67f26
commit 5982165128
5 changed files with 75 additions and 3 deletions
@@ -21,7 +21,7 @@ class LinkRedirectController extends Controller
{
if ($path === null || $path === '') {
$link = $this->links->resolve($request, $slug);
if ($link !== null) {
if ($link !== null && $link->isDirectRedirect()) {
return redirect()->away($link->destination_url, 302);
}
}
+6
View File
@@ -64,6 +64,12 @@ class ShortLink extends Model
return $this->expires_at !== null && $this->expires_at->isPast();
}
/** Simple URL redirects created in Link; QR ecosystem slugs resolve via the platform proxy. */
public function isDirectRedirect(): bool
{
return $this->is_managed_here && $this->source_kind === 'redirect';
}
public function sourceAppLabel(): string
{
return match ($this->source_app) {
+1 -1
View File
@@ -40,7 +40,7 @@ class LinkCatalogSyncService
[
'user_id' => $user->id,
'label' => $row['label'] ?? null,
'destination_url' => (string) ($row['destination_url'] ?? LadillLink::url($slug)),
'destination_url' => (string) ($row['destination_summary'] ?? $row['destination_url'] ?? LadillLink::url($slug)),
'source_app' => (string) ($row['source_app'] ?? 'platform'),
'source_kind' => (string) ($row['source_kind'] ?? 'qr'),
'source_ref' => isset($row['source_ref']) ? (string) $row['source_ref'] : null,
+4 -1
View File
@@ -24,8 +24,11 @@ class LinkPlatformProxy
$target .= '?'.$qs;
}
$client = Http::withOptions(['allow_redirects' => false])->timeout(15);
$method = strtoupper($request->method());
$followRedirects = $method === 'GET' || $method === 'HEAD';
$client = Http::withOptions([
'allow_redirects' => $followRedirects ? ['max' => 5] : false,
])->timeout(15);
$pending = match ($method) {
'POST' => $client->withHeaders($this->forwardHeaders($request))->asForm()->post($target, $request->post()),
+63
View File
@@ -0,0 +1,63 @@
<?php
namespace Tests\Feature;
use App\Models\ShortLink;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;
use Tests\TestCase;
class LinkRedirectTest extends TestCase
{
use RefreshDatabase;
private function user(): User
{
return User::create([
'public_id' => (string) Str::uuid(),
'name' => 'Test',
'email' => 'test+'.uniqid().'@example.com',
]);
}
public function test_direct_redirect_links_go_to_destination_url(): void
{
$user = $this->user();
ShortLink::create([
'user_id' => $user->id,
'slug' => 'direct1',
'source_app' => 'link',
'source_kind' => 'redirect',
'is_managed_here' => true,
'destination_url' => 'https://example.com/target',
'is_active' => true,
]);
$this->get('https://ladl.link/direct1')
->assertRedirect('https://example.com/target');
}
public function test_catalog_qr_links_proxy_to_platform_instead_of_bad_destination(): void
{
$user = $this->user();
ShortLink::create([
'user_id' => $user->id,
'slug' => 'qrpage',
'source_app' => 'qrplus',
'source_kind' => 'qr',
'is_managed_here' => false,
'destination_url' => 'https://ladl.link/qrpage · Link list page',
'is_active' => true,
]);
Http::fake([
'https://ladill.com/q/qrpage' => Http::response('<html>QR page</html>', 200),
]);
$this->get('https://ladl.link/qrpage')
->assertOk()
->assertSee('QR page');
}
}