38 lines
1.4 KiB
PHP
38 lines
1.4 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
/**
|
|
* Router for local dev (`php -S localhost:8000 scripts/dev-router.php`).
|
|
*
|
|
* PHP's built-in server ignores .htaccess, so without this it would serve
|
|
* the SQLite database, includes, and project files to anyone who can
|
|
* reach it — including other devices on the LAN via browser-sync.
|
|
* Anything not blocked falls through to the built-in server as normal.
|
|
*/
|
|
|
|
$path = rawurldecode(parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH) ?: '/');
|
|
$path = preg_replace('#/+#', '/', $path);
|
|
|
|
// Case-insensitive: macOS's filesystem is, so /DB/fitz.sqlite would match.
|
|
$blocked = '#^/(?:db|inc|bin|scripts|src|dist|node_modules)(?:/|$)'
|
|
. '|(?:^|/)\.'
|
|
. '|^/(?:package(?:-lock)?\.json|docker-compose\.ya?ml|config(?:\.example)?\.php)$#i';
|
|
|
|
if (preg_match($blocked, $path)) {
|
|
http_response_code(404);
|
|
echo 'Not Found';
|
|
return true;
|
|
}
|
|
|
|
// Apache (mod_dir) redirects /admin to /admin/; the built-in server just
|
|
// serves admin/index.php at /admin. Every relative link on that page then
|
|
// resolves against / instead of /admin/ — "menu.php" lands on the public
|
|
// menu, "users.php" 404s. Match Apache so dev behaves like production.
|
|
if ($path !== '/' && !str_ends_with($path, '/') && is_dir(__DIR__ . '/..' . $path)) {
|
|
$query = parse_url($_SERVER['REQUEST_URI'] ?? '', PHP_URL_QUERY);
|
|
header('Location: ' . $path . '/' . ($query ? '?' . $query : ''), true, 301);
|
|
return true;
|
|
}
|
|
|
|
return false;
|