Files
projectsend/tests/Unit/RouteRedirectDestinationsTest.php
ignacionelson 6e47d76ba6 ProjectSend 2.0.0
Client file sharing, rebuilt from the ground up: a private area per
client, resumable uploads, folders, groups and categories, sharing with
expiry dates and download limits, comments, file versions, an activity
log, a REST API, and sixteen languages.

This repository begins here. ProjectSend 2 was developed privately, and
that development history is not published — the previous generation
remains available, with its own history, at projectsend/legacy.

Free software under the GNU General Public License v2, or (at your
option) any later version.
2026-08-14 01:38:12 -03:00

46 lines
1.8 KiB
PHP

<?php
declare(strict_types=1);
/**
* Route::redirect()'s destination needs a leading slash, or Laravel
* deliberately emits a *relative* Location header instead of an
* absolute one (Illuminate\Routing\RedirectController strips the
* leading slash it would otherwise generate whenever the destination
* you passed doesn't have one). A browser resolves a relative Location
* against the current path's directory — for a source path more than
* one segment deep, that silently redirects somewhere wrong (e.g.
* 'system/settings' -> 'system/settings/general' resolves to
* '/system/system/settings/general', a 404) instead of throwing.
*
* This genuinely can't be caught with an HTTP feature test:
* TestResponse::assertRedirect() normalizes both sides through
* url()->to() before comparing, which erases the exact relative-vs-
* absolute distinction that breaks a real browser — and, confirmed
* empirically, even asserting the raw Location header directly still
* doesn't reproduce the bug under Laravel's test HTTP kernel, only
* against a real request through the actual web server. A static
* source check is the only reliable way to keep this from regressing.
*/
test('every Route::redirect() destination in routes/ uses a leading-slash absolute path', function () {
$offenders = [];
foreach (glob(__DIR__.'/../../routes/*.php') as $file) {
$contents = file_get_contents($file);
preg_match_all(
"/Route::redirect\\(\\s*'[^']*'\\s*,\\s*'([^']*)'/",
$contents,
$matches,
);
foreach ($matches[1] as $destination) {
if (! str_starts_with($destination, '/')) {
$offenders[] = basename($file).': '.$destination;
}
}
}
expect($offenders)->toBe([]);
});