Files
frontend/apps/as/app/api/proxy/[...url]/route.ts
T

112 lines
3.3 KiB
TypeScript

import { cookies } from "next/headers";
import { NextResponse } from "next/server";
import {
ACCESS_TOKEN,
AUTH_USER_ID,
CLAIM_NAME,
REFRESH_TOKEN,
SERVER_API_URL,
SITE_ID,
} from "@/shared/config";
async function handler(
request: Request,
params: { url: string[] },
method: "GET" | "POST" | "PUT" | "DELETE",
) {
const cookieStore = await cookies();
const headers: Record<string, string> = {
"Content-Type": "application/json",
"X-Site-Id": SITE_ID,
};
let body = {};
const isRefreshHandler = params.url.includes("refresh");
// 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();
}
const targetUrl = `${SERVER_API_URL}/${params.url.join("/")}`;
console.log(`[Proxy API] ${method} ${params.url.join("/")} -> ${targetUrl}`);
console.log(`[Proxy API] Headers:`, headers);
if (!isRefreshHandler) {
console.log(`[Proxy API] Body:`, body);
}
const result = await fetch(targetUrl, {
method,
headers,
body: JSON.stringify(body),
});
console.log(`[Proxy API] Response Status: ${result.status}`);
console.log(`[Proxy API] Response Headers:`, {
[ACCESS_TOKEN]: result.headers.get(ACCESS_TOKEN),
[REFRESH_TOKEN]: result.headers.get(REFRESH_TOKEN) ? '***hidden***' : undefined,
[AUTH_USER_ID]: result.headers.get(AUTH_USER_ID),
});
if (!result.ok) {
console.error(`[Proxy API] Request failed with status ${result.status}`);
return NextResponse.json({ message: "Invalid Credentials" }, { status: 401 });
}
const accessToken = result.headers.get(ACCESS_TOKEN);
const refreshToken = result.headers.get(REFRESH_TOKEN);
const userId = result.headers.get(AUTH_USER_ID);
if (accessToken && userId) {
console.log(`[Proxy API] Login successful for user: ${userId}`);
const response = NextResponse.json({
[ACCESS_TOKEN]: accessToken,
[AUTH_USER_ID]: userId,
});
const forwardedHost = request.headers.get("x-forwarded-host");
const host = request.headers.get("host");
const actualHost = forwardedHost || host || new URL(request.url).hostname.toString();
// 운영 환경에서 domain 설정
const domain = actualHost.includes("hasuon.or.kr") ? ".hasuon.or.kr" : actualHost;
if (refreshToken) {
cookieStore.set(REFRESH_TOKEN, refreshToken, {
httpOnly: true,
sameSite: "strict",
domain: domain,
path: "/",
});
}
return response;
}
return NextResponse.json({ message: "Invalid Credentials" }, { status: 401 });
} catch (error) {
console.error(`[Proxy API] Error caught in handler:`, 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");
}