withRouting( web: __DIR__.'/../routes/web.php', commands: __DIR__.'/../routes/console.php', health: '/up', ) ->withMiddleware(function (Middleware $middleware): void { $middleware->web(append: [SetLocale::class]); // Trust the reverse proxy (e.g. BunkerWeb) so Laravel correctly // detects HTTPS and the client IP from X-Forwarded-* headers. // Set TRUSTED_PROXIES to "*" to trust the calling IP, or a // comma-separated list of proxy IPs/CIDRs; defaults to none. // // NOTE: this runs before the config repository is bootstrapped, so // it must use env() rather than config(). If APP_ENV is cached via // `config:cache`, .env is no longer parsed at boot either — set // TRUSTED_PROXIES as a real process env var (e.g. in the PHP-FPM // pool's `env[]`) rather than only in .env. $trustedProxies = trim((string) env('TRUSTED_PROXIES', '')); $middleware->trustProxies( at: match (true) { $trustedProxies === '' => null, $trustedProxies === '*' => '*', default => array_filter(array_map('trim', explode(',', $trustedProxies))), }, headers: Request::HEADER_X_FORWARDED_FOR | Request::HEADER_X_FORWARDED_HOST | Request::HEADER_X_FORWARDED_PORT | Request::HEADER_X_FORWARDED_PROTO, ); // Moneybird's webhook POSTs carry no CSRF token — it's verified via // its own shared webhook_token instead (see MoneybirdWebhookController). $middleware->validateCsrfTokens(except: [ 'webhooks/moneybird', ]); }) ->withExceptions(function (Exceptions $exceptions): void { $exceptions->shouldRenderJsonWhen( fn (Request $request) => $request->is('api/*') || $request->expectsJson(), ); })->create();