fix: 운영실태(fo), 물재이용(wr) 프록시 라우트 파일 추가

This commit is contained in:
swcho
2025-10-21 15:11:12 +09:00
parent 77dd04a140
commit 0585a6d8df
7 changed files with 253 additions and 5 deletions
+111
View File
@@ -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<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 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");
}
+2 -2
View File
@@ -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
@@ -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);
+3 -1
View File
@@ -60,7 +60,9 @@ export const postData = async (url: string, data: object): Promise<any> => {
};
export const postMutiPart = async (url: string, data: FormData): Promise<any> => {
const res = await axios.post(`${BASE_URL}/${url}`, data);
const res = await axios.post(`${BASE_URL}/${url}`, data, {
timeout: 600000, // 10분
});
return res.data;
};
@@ -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);
}
+13 -2
View File
@@ -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")) {
+111
View File
@@ -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<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 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");
}