clusev/bootstrap/app.php

46 lines
2.1 KiB
PHP

<?php
use App\Http\Middleware\PanelScheme;
use App\Http\Middleware\SecurityHeaders;
use App\Http\Middleware\SetLocale;
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
use Illuminate\Http\Request;
return Application::configure(basePath: dirname(__DIR__))
->withRouting(
web: __DIR__.'/../routes/web.php',
commands: __DIR__.'/../routes/console.php',
health: '/up',
)
// Registers the `/broadcasting/auth` endpoint (under the `web` group, so PanelScheme
// guards it) and the private-channel authorization callbacks in routes/channels.php.
// Without this, private/presence channels can never be subscribed to. See R-note in
// routes/channels.php: every broadcast channel is PRIVATE (authenticated) — metrics are
// fleet infrastructure data and must not be reachable on a stale Caddy host via Reverb.
->withBroadcasting(__DIR__.'/../routes/channels.php')
->withMiddleware(function (Middleware $middleware): void {
// Trust Caddy's X-Forwarded-* ONLY in production, where the app has no host port
// (docker-compose.prod.yml exposes app:80 on the internal net only) so Caddy is
// the sole peer. In dev the app port is published on the host, so trusting forged
// proxy headers would let a LAN peer fake HTTPS (forcing a Secure cookie over
// plain HTTP and breaking the bare-IP recovery login).
if (($_SERVER['APP_ENV'] ?? getenv('APP_ENV') ?: 'local') === 'production') {
$middleware->trustProxies(at: '*');
}
// PanelScheme first (scheme/host enforcement before auth), so an HTTP request to
// the active domain is sent straight to HTTPS and a wrong host is refused before
// any auth redirect.
$middleware->web(
prepend: [PanelScheme::class],
append: [SetLocale::class, SecurityHeaders::class],
);
})
->withExceptions(function (Exceptions $exceptions): void {
$exceptions->shouldRenderJsonWhen(
fn (Request $request) => $request->is('api/*'),
);
})->create();