Files
chatroom/bootstrap/app.php
T
2026-05-05 21:55:48 +08:00

88 lines
3.7 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* 文件功能:Laravel 应用启动配置。
* 负责注册路由、中间件别名、代理信任规则与全局异常响应格式。
*/
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
use Illuminate\Http\Request;
use Illuminate\Session\TokenMismatchException;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
return Application::configure(basePath: dirname(__DIR__))
->withRouting(
web: __DIR__.'/../routes/web.php',
commands: __DIR__.'/../routes/console.php',
channels: __DIR__.'/../routes/channels.php',
health: '/up',
)
->withMiddleware(function (Middleware $middleware) {
$trustedProxies = array_values(array_filter(array_map(
static fn (string $proxy): string => trim($proxy),
explode(',', (string) env('TRUSTED_PROXIES', '127.0.0.1,::1'))
)));
// 强制解析并信任 CDN (如 Cloudflare) 透传的真实 IP (最高优先级)
$middleware->prepend(\App\Http\Middleware\CloudflareProxies::class);
// 仅信任显式配置的反向代理 / CDN 节点,避免外部客户端伪造转发头污染 request()->ip()。
// 生产环境需要把实际代理 IP / CIDR 写入 TRUSTED_PROXIES。
$middleware->trustProxies(at: empty($trustedProxies) ? null : $trustedProxies);
$middleware->alias([
'chat.auth' => \App\Http\Middleware\ChatAuthenticate::class,
'chat.level' => \App\Http\Middleware\LevelRequired::class,
'chat.site_owner' => \App\Http\Middleware\SiteOwnerRequired::class,
'chat.has_position' => \App\Http\Middleware\HasActivePosition::class,
]);
// 这一步是为了防止用户访问需要登录的页面时,默认被跳到原版 Laravel 未定义的 login 路由报错
$middleware->redirectGuestsTo('/');
})
->withExceptions(function (Exceptions $exceptions): void {
$isJsonSessionRequest = static function (Request $request): bool {
if ($request->expectsJson() || $request->ajax()) {
return true;
}
return $request->is(
'room/*/send',
'room/*/heartbeat',
'room/*/leave',
'room/*/announcement',
'gift/*',
'command/*',
'chatbot/*',
'shop/*'
);
};
$expiredSessionResponse = static function () {
return response()->json([
'status' => 'error',
'code' => 'SESSION_EXPIRED',
'message' => '登录状态已失效,请刷新页面后重新登录。',
'reload' => true,
'login_url' => route('home'),
], 419);
};
// CSRF token 失效通常意味着页面还停留在旧会话里;JSON 请求统一返回业务提示,避免泄露框架异常堆栈。
$exceptions->render(function (TokenMismatchException $e, Request $request) use ($expiredSessionResponse, $isJsonSessionRequest) {
if ($isJsonSessionRequest($request)) {
return $expiredSessionResponse();
}
});
// Laravel 在某些环境下会先把 TokenMismatchException 包装成 419 HttpException
// 这里补一层兜底,确保接口始终返回稳定 JSON,而不是默认异常结构。
$exceptions->render(function (HttpExceptionInterface $e, Request $request) use ($expiredSessionResponse, $isJsonSessionRequest) {
if ($e->getStatusCode() === 419 && $isJsonSessionRequest($request)) {
return $expiredSessionResponse();
}
});
})->create();