isDownForMaintenance()) { return $next($request); } // secret 쿠키가 있으면 통과 (관리자 접근) if ($this->hasValidBypassCookie($request)) { return $next($request); } // 로케일 감지 (SetLocale 미들웨어가 실행되지 않으므로 자체 감지) // API/HTML 분기보다 먼저 적용해야 JSON 응답 메시지도 ja 등 활성 언어팩 로케일을 반영한다 $locale = $this->detectLocale($request); app()->setLocale($locale); // API 요청은 JSON 응답 if ($request->expectsJson() || $request->is('api/*')) { return response()->json([ 'success' => false, 'message' => __('maintenance.message'), ], 503); } // 정적 메인터넌스 페이지 렌더링 (DB/API/JS 무의존) return response()->view('maintenance', [], 503); } /** * 유효한 bypass 쿠키가 있는지 확인합니다. * * @param Request $request HTTP 요청 * @return bool */ protected function hasValidBypassCookie(Request $request): bool { $downFilePath = storage_path('framework/down'); if (! file_exists($downFilePath)) { return false; } $data = json_decode(file_get_contents($downFilePath), true); if (! isset($data['secret'])) { return false; } $cookie = $request->cookie('laravel_maintenance'); if (! $cookie) { return false; } return MaintenanceModeBypassCookie::isValid($cookie, $data['secret']); } /** * 로케일을 감지합니다. SetLocale 미들웨어의 로직을 준용합니다. * * @param Request $request HTTP 요청 * @return string 감지된 로케일 */ protected function detectLocale(Request $request): string { $supportedLocales = config('app.supported_locales', ['ko', 'en']); $acceptLanguage = $request->header('Accept-Language'); if ($acceptLanguage) { $languages = explode(',', $acceptLanguage); foreach ($languages as $language) { $lang = trim(explode(';', $language)[0]); if (strpos($lang, '-') !== false) { $lang = explode('-', $lang)[0]; } if (in_array($lang, $supportedLocales)) { return $lang; } } } return config('app.locale', 'ko'); } }