diff --git a/apps/fo/app/api/proxy/[...url]/route.ts b/apps/fo/app/api/proxy/[...url]/route.ts new file mode 100644 index 000000000..cf6447b1a --- /dev/null +++ b/apps/fo/app/api/proxy/[...url]/route.ts @@ -0,0 +1,111 @@ +/** + * πŸ“„ Proxy Route + * API ν”„λ‘μ‹œ 라우트 + * + * - μ„œλ²„ API둜의 μš”μ²­ ν”„λ‘μ‹œ 처리 + * - μΏ ν‚€ 기반 인증 토큰 및 λ¦¬ν”„λ ˆμ‹œ 토큰 관리 + * - POST 및 PUT μš”μ²­ 핸듀링 + * - μ‚¬μš©μž 인증 정보 검증 및 응닡 처리 + * - μ—λŸ¬ 핸듀링 및 μƒνƒœ μ½”λ“œ λ°˜ν™˜ + * - μ‚¬μ΄νŠΈ ID 및 헀더 μ„€μ • + */ +import { cookies } from "next/headers"; +import { NextResponse } from "next/server"; + +const ACCESS_TOKEN = process.env.NEXT_PUBLIC_ACCESS_TOKEN || "access-token"; +const AUTH_USER_ID = process.env.NEXT_PUBLIC_AUTH_USER_ID || "token-id"; +const CLAIM_NAME = process.env.NEXT_PUBLIC_CLAIM_NAME || "Authorization"; +const REFRESH_TOKEN = process.env.NEXT_PUBLIC_REFRESH_TOKEN || "refresh-token"; +const SERVER_API_URL = process.env.NEXT_PUBLIC_SERVER_API_URL || ""; +const SITE_ID = process.env.NEXT_PUBLIC_SITE_ID || "SN"; + +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"); + + // 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 result = await fetch(`${SERVER_API_URL}/${params.url.join("/")}`, { + method, + headers, + body: JSON.stringify(body), + }); + + if (!result.ok) { + console.log("Invalid Credentials "); + 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) { + const response = NextResponse.json({ + [ACCESS_TOKEN]: accessToken, + [AUTH_USER_ID]: userId, + }); + + if (refreshToken) { + cookieStore.set(REFRESH_TOKEN, refreshToken, { + httpOnly: true, + sameSite: "lax", + path: "/", + }); + } + + return response; + } + + return NextResponse.json( + { message: "Invalid Credentials" }, + { status: 401 }, + ); + } catch (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"); +} diff --git a/apps/sn/.env.local b/apps/sn/.env.local index 41b18da0c..6cde78209 100644 --- a/apps/sn/.env.local +++ b/apps/sn/.env.local @@ -11,9 +11,9 @@ NEXT_PUBLIC_LX_GEOSERVER_URL = http://con.mind-one.co.kr:11306/geoserver #NEXT_PUBLIC_NGII_URL = https://map.ngii.go.kr/openapi/Gettile.do?apiKey=04trYP9_xwLAfALjwZ-B8g NEXT_PUBLIC_NGII_URL = https://map.ngii.go.kr/openapi/Gettile.do?apiKey=04trYP9_xwLAfALjwZ-B8g&layer=korean_map&TileMatrix={z}&TileCol={x}&TileRow={y} NEXT_PUBLIC_SERVER_API_URL = http://dev.onasys.co.kr:8000 -NEXT_PUBLIC_SEWERAGE_API_URL = http://con.mind-one.co.kr:11083 +# NEXT_PUBLIC_SEWERAGE_API_URL = http://con.mind-one.co.kr:11083 NEXT_PUBLIC_DC_URL = https://apigateway.apps.rsonesoft.com NEXT_PUBLIC_CM_LOGIN_PAGE_URL = http://dev.onasys.co.kr:3000/auth/login #NEXT_PUBLIC_SEWERAGE_API_URL=http://192.168.1.128:8883 #NEXT_PUBLIC_SEWERAGE_API_URL=http://192.168.1.222:8883 -# NEXT_PUBLIC_SEWERAGE_API_URL=http://192.168.1.66:8883 +NEXT_PUBLIC_SEWERAGE_API_URL=http://192.168.1.66:8883 diff --git a/apps/sn/app/(with-base-layout)/oper/floodPre/page.tsx b/apps/sn/app/(with-base-layout)/oper/floodPre/page.tsx index 3b547cf09..af62b397f 100644 --- a/apps/sn/app/(with-base-layout)/oper/floodPre/page.tsx +++ b/apps/sn/app/(with-base-layout)/oper/floodPre/page.tsx @@ -151,7 +151,9 @@ const Page = () => { sbmrgPrevntBizNm: fileName, rgtr: tokenManager.getToken(AUTH_USER_ID) || null } + console.log('registFile json =>', json); const data = await postData('v1/sbmrgPrevnt', json) + console.log('registFile data =>', data); if (data) { alert('파일이 λ“±λ‘λ˜μ—ˆμŠ΅λ‹ˆλ‹€.'); setIsUploadModalOpen(false); diff --git a/apps/sn/app/components/lib/api/index.ts b/apps/sn/app/components/lib/api/index.ts index e94c602c1..6b668294d 100644 --- a/apps/sn/app/components/lib/api/index.ts +++ b/apps/sn/app/components/lib/api/index.ts @@ -60,7 +60,9 @@ export const postData = async (url: string, data: object): Promise => { }; export const postMutiPart = async (url: string, data: FormData): Promise => { - const res = await axios.post(`${BASE_URL}/${url}`, data); + const res = await axios.post(`${BASE_URL}/${url}`, data, { + timeout: 600000, // 10λΆ„ + }); return res.data; }; diff --git a/apps/sn/app/components/ui/fileUploadForm.tsx b/apps/sn/app/components/ui/fileUploadForm.tsx index fc1e2b779..750effb66 100644 --- a/apps/sn/app/components/ui/fileUploadForm.tsx +++ b/apps/sn/app/components/ui/fileUploadForm.tsx @@ -72,6 +72,11 @@ const FileUploadForm = ({ handleUploadWithResponse(files, currentFile) .then(({ atflCd, atflId }) => { // μ—…λ‘œλ“œ μ™„λ£Œ ν›„ onSubmit μ‹€ν–‰ + console.log('fileNm', fileNm); + console.log('selectedYear', selectedYear); + console.log('selectedQuarter', selectedQuarter); + console.log('atflCd', atflCd); + console.log('atflId', atflId); onSubmit(fileNm, selectedYear, selectedQuarter, atflCd || '', atflId || ''); // UI μ΄ˆκΈ°ν™” @@ -120,6 +125,8 @@ const FileUploadForm = ({ reject(error); }; + console.log('Starting upload for files:', files); + // κΈ°μ‘΄ handleUpload μœ ν‹Έλ¦¬ν‹° μ‚¬μš© (μˆ˜μ •ν•˜μ§€ μ•ŠμŒ) handleUpload(files, { handleUploadStart: setUpload, @@ -160,6 +167,10 @@ const FileUploadForm = ({ setFileName(firstFile.name); setCurrentFile(firstFile); + console.log('selectedFiles', selectedFiles); + console.log('firstFile', firstFile); + console.log('firstFile name', firstFile.name); + if (onFileSelect) { onFileSelect(firstFile, internalAtflCd, internalAtflId); } diff --git a/apps/sn/middleware.ts b/apps/sn/middleware.ts index 9851437b1..8d20a60c0 100644 --- a/apps/sn/middleware.ts +++ b/apps/sn/middleware.ts @@ -104,9 +104,20 @@ export function middleware(req: NextRequest) { || pathname.startsWith("/cms-service") || pathname.startsWith("/user-service") ) { + const requestHeaders = new Headers(req.headers); + const token = req.cookies.get(CLAIM_NAME)?.value; + const userId = req.cookies.get(AUTH_USER_ID)?.value; const newUrl = `${SERVER_API_URL}${pathname}`; - console.log(`[Middleware] Rewriting from '/attach-service' path to: ${newUrl}`); - return rewriteWith(newUrl, req, true); + + if (token) requestHeaders.set(CLAIM_NAME, token); + if (userId) requestHeaders.set(AUTH_USER_ID, userId); + + console.log( + `[Middleware] Rewriting from '/attach-service' path to: ${newUrl}`, + ); + return NextResponse.rewrite(new URL(newUrl), { + headers: requestHeaders, + }); } if (pathname.startsWith("/dc-service")) { diff --git a/apps/wr/app/api/proxy/[...url]/route.ts b/apps/wr/app/api/proxy/[...url]/route.ts new file mode 100644 index 000000000..cf6447b1a --- /dev/null +++ b/apps/wr/app/api/proxy/[...url]/route.ts @@ -0,0 +1,111 @@ +/** + * πŸ“„ Proxy Route + * API ν”„λ‘μ‹œ 라우트 + * + * - μ„œλ²„ API둜의 μš”μ²­ ν”„λ‘μ‹œ 처리 + * - μΏ ν‚€ 기반 인증 토큰 및 λ¦¬ν”„λ ˆμ‹œ 토큰 관리 + * - POST 및 PUT μš”μ²­ 핸듀링 + * - μ‚¬μš©μž 인증 정보 검증 및 응닡 처리 + * - μ—λŸ¬ 핸듀링 및 μƒνƒœ μ½”λ“œ λ°˜ν™˜ + * - μ‚¬μ΄νŠΈ ID 및 헀더 μ„€μ • + */ +import { cookies } from "next/headers"; +import { NextResponse } from "next/server"; + +const ACCESS_TOKEN = process.env.NEXT_PUBLIC_ACCESS_TOKEN || "access-token"; +const AUTH_USER_ID = process.env.NEXT_PUBLIC_AUTH_USER_ID || "token-id"; +const CLAIM_NAME = process.env.NEXT_PUBLIC_CLAIM_NAME || "Authorization"; +const REFRESH_TOKEN = process.env.NEXT_PUBLIC_REFRESH_TOKEN || "refresh-token"; +const SERVER_API_URL = process.env.NEXT_PUBLIC_SERVER_API_URL || ""; +const SITE_ID = process.env.NEXT_PUBLIC_SITE_ID || "SN"; + +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"); + + // 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 result = await fetch(`${SERVER_API_URL}/${params.url.join("/")}`, { + method, + headers, + body: JSON.stringify(body), + }); + + if (!result.ok) { + console.log("Invalid Credentials "); + 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) { + const response = NextResponse.json({ + [ACCESS_TOKEN]: accessToken, + [AUTH_USER_ID]: userId, + }); + + if (refreshToken) { + cookieStore.set(REFRESH_TOKEN, refreshToken, { + httpOnly: true, + sameSite: "lax", + path: "/", + }); + } + + return response; + } + + return NextResponse.json( + { message: "Invalid Credentials" }, + { status: 401 }, + ); + } catch (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"); +}