import { ACCESS_TOKEN, AUTH_USER_ID, CLAIM_NAME, REFRESH_TOKEN, SERVER_API_URL, SITE_ID, } from "@/shared/config"; import { cookies } from "next/headers"; import { NextResponse } from "next/server"; async function handler( request: Request, params: { url: string[] }, method: "GET" | "POST" | "PUT" | "DELETE", ) { const cookieStore = await cookies(); const headers: Record = { "Content-Type": "application/json", "X-Site-Id": SITE_ID, }; let body = {}; const isRefreshHandler = params.url.includes("refresh"); console.log(`[Proxy] ${method} ${params.url.join("/")}`); console.log(`[Proxy] Server API URL: ${SERVER_API_URL}`); // silent refresh if (isRefreshHandler) { const refreshToken = cookieStore.get(REFRESH_TOKEN); headers[CLAIM_NAME] = refreshToken?.value ?? ""; if (!headers[CLAIM_NAME]) { return NextResponse.json({ message: "Can't refresh" }, { status: 401 }); } } try { if (!isRefreshHandler) { body = await request.json(); console.log(`[Proxy] Request body:`, body); } const targetUrl = `${SERVER_API_URL}/${params.url.join("/")}`; console.log(`[Proxy] Target URL: ${targetUrl}`); const result = await fetch(targetUrl, { method, headers, body: JSON.stringify(body), }); console.log(`[Proxy] Response status: ${result.status}`); console.log(`[Proxy] Response headers:`, Object.fromEntries(result.headers.entries())); // 2FA 관련 엔드포인트인 경우 응답 본문도 확인 const is2FAEndpoint = params.url.includes("2fa") || params.url.includes("auth"); let responseData = {}; if (is2FAEndpoint) { try { responseData = await result.json(); console.log(`[Proxy] 2FA Response data:`, responseData); } catch { // JSON 파싱 실패 시 빈 객체 사용 console.log(`[Proxy] Failed to parse JSON response`); } } const accessToken = result.headers.get(ACCESS_TOKEN) || result.headers.get('ss-token'); const refreshToken = result.headers.get(REFRESH_TOKEN); const userId = result.headers.get(AUTH_USER_ID); console.log(`[Proxy] Tokens - accessToken: ${!!accessToken}, userId: ${!!userId}, refreshToken: ${!!refreshToken}`); console.log(`[Proxy] Available headers:`, Array.from(result.headers.keys())); // 2FA 엔드포인트이고 실패한 경우 실제 오류 메시지 반환 if (!result.ok && is2FAEndpoint) { console.log(`[Proxy] 2FA endpoint failed, returning actual error`); return NextResponse.json(responseData, { status: result.status }); } // 2FA 엔드포인트이고 성공한 경우 (토큰이 헤더에 없을 수 있음) if (result.ok && is2FAEndpoint) { console.log(`[Proxy] 2FA endpoint succeeded, returning response data`); return NextResponse.json(responseData, { status: result.status }); } // 일반적인 실패 처리 if (!result.ok) { console.log(`[Proxy] General endpoint failed`); return NextResponse.json( { message: "Invalid Credentials" }, { status: 401 }, ); } if (accessToken && userId) { const response = NextResponse.json({ [ACCESS_TOKEN]: accessToken, [AUTH_USER_ID]: userId, ...responseData, // 2FA 관련 추가 데이터 포함 }); if (refreshToken) { cookieStore.set(REFRESH_TOKEN, refreshToken, { httpOnly: true, sameSite: "lax", path: "/", }); } console.log(`[Proxy] Success response sent`); return response; } console.log(`[Proxy] Missing tokens in response`); return NextResponse.json( { message: "Invalid Credentials" }, { status: 401 }, ); } catch (error) { console.error(`[Proxy] Error:`, error); return NextResponse.json( { message: "Server Error", error }, { status: 500 }, ); } } export async function POST( request: Request, props: { params: Promise<{ url: string[] }> }, ) { const params = await props.params; return handler(request, params, "POST"); } export async function PUT( request: Request, props: { params: Promise<{ url: string[] }> }, ) { const params = await props.params; return handler(request, params, "PUT"); }