withRouting( health: '/up', then: function (): void { Route::middleware(['web', 'throttle:5,2']) ->post('/csp-report', function (): void { $isCspRequest = request()->header('Content-Type') === 'application/csp-report'; abort_if( ! $isCspRequest or ! request()->json('csp-report') or ! is_array(request()->json('csp-report')), 401, ); /** @var array $rawReport */ $rawReport = request()->json('csp-report'); // * Flatten if needed. $cspReport = collect($rawReport) ->flatMap(fn (mixed $v, string $k) => [ $k => is_array($v) ? collect($v)->flatten()->implode(', ') : (string) $v, ])->all(); // * Filter array keys. $cspReport = collect(array_intersect_key($cspReport, [ 'blocked-uri' => '', 'document-uri' => '', 'original-policy' => '', 'referrer' => '', 'violated-directive' => '', ])); Log::warning(sprintf( "CSP REPORT for %s : \n %s", $cspReport->get('document-uri'), $cspReport->implode("\n") )); })->name('cspReportUri'); } ) ->withMiddleware(function (Middleware $middleware): void { $middleware->web(append: [ \Uwil\LaravelI18n\Middlewares\ForceLocale::class, HandleInertiaRequests::class, AddLinkHeadersForPreloadedAssets::class, SecureHeaders::class, TrimStrings::class, TrustHosts::class, TrustProxies::class, ]); $middleware->preventRequestForgery(except: [ '/csp-report', ]); }) ->withExceptions(function (Exceptions $exceptions): void { $exceptions->render(function (HttpException $e, Request $request) { $status = $e->getStatusCode(); return InertiaHelper::errorRender($request, $status); }); /** * Automatic exception capture with Sentry. */ $exceptions->report(function (\Throwable $e): void { if (app()->bound('sentry')) { resolve('sentry')->captureException($e); } }); /** * Handling validation errors by excluding sensitive fields from the flash. */ $exceptions->render(function (ValidationException $e, Request $request) { $safeInput = collect($request->all()) ->except(['password', 'password_confirmation', 'current_password']) ->toArray(); return back() ->withInput($safeInput) ->withErrors($e->errors()); }); })->create();