fix: 운영실태(fo), 물재이용(wr) 프록시 라우트 파일 추가
This commit is contained in:
@@ -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
@@ -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
|
||||||
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_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_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_DC_URL = https://apigateway.apps.rsonesoft.com
|
||||||
NEXT_PUBLIC_CM_LOGIN_PAGE_URL = http://dev.onasys.co.kr:3000/auth/login
|
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.128:8883
|
||||||
#NEXT_PUBLIC_SEWERAGE_API_URL=http://192.168.1.222: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,
|
sbmrgPrevntBizNm: fileName,
|
||||||
rgtr: tokenManager.getToken(AUTH_USER_ID) || null
|
rgtr: tokenManager.getToken(AUTH_USER_ID) || null
|
||||||
}
|
}
|
||||||
|
console.log('registFile json =>', json);
|
||||||
const data = await postData('v1/sbmrgPrevnt', json)
|
const data = await postData('v1/sbmrgPrevnt', json)
|
||||||
|
console.log('registFile data =>', data);
|
||||||
if (data) {
|
if (data) {
|
||||||
alert('파일이 등록되었습니다.');
|
alert('파일이 등록되었습니다.');
|
||||||
setIsUploadModalOpen(false);
|
setIsUploadModalOpen(false);
|
||||||
|
|||||||
@@ -60,7 +60,9 @@ export const postData = async (url: string, data: object): Promise<any> => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const postMutiPart = async (url: string, data: FormData): 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;
|
return res.data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -72,6 +72,11 @@ const FileUploadForm = ({
|
|||||||
handleUploadWithResponse(files, currentFile)
|
handleUploadWithResponse(files, currentFile)
|
||||||
.then(({ atflCd, atflId }) => {
|
.then(({ atflCd, atflId }) => {
|
||||||
// 업로드 완료 후 onSubmit 실행
|
// 업로드 완료 후 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 || '');
|
onSubmit(fileNm, selectedYear, selectedQuarter, atflCd || '', atflId || '');
|
||||||
|
|
||||||
// UI 초기화
|
// UI 초기화
|
||||||
@@ -120,6 +125,8 @@ const FileUploadForm = ({
|
|||||||
reject(error);
|
reject(error);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
console.log('Starting upload for files:', files);
|
||||||
|
|
||||||
// 기존 handleUpload 유틸리티 사용 (수정하지 않음)
|
// 기존 handleUpload 유틸리티 사용 (수정하지 않음)
|
||||||
handleUpload(files, {
|
handleUpload(files, {
|
||||||
handleUploadStart: setUpload,
|
handleUploadStart: setUpload,
|
||||||
@@ -160,6 +167,10 @@ const FileUploadForm = ({
|
|||||||
setFileName(firstFile.name);
|
setFileName(firstFile.name);
|
||||||
setCurrentFile(firstFile);
|
setCurrentFile(firstFile);
|
||||||
|
|
||||||
|
console.log('selectedFiles', selectedFiles);
|
||||||
|
console.log('firstFile', firstFile);
|
||||||
|
console.log('firstFile name', firstFile.name);
|
||||||
|
|
||||||
if (onFileSelect) {
|
if (onFileSelect) {
|
||||||
onFileSelect(firstFile, internalAtflCd, internalAtflId);
|
onFileSelect(firstFile, internalAtflCd, internalAtflId);
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-2
@@ -104,9 +104,20 @@ export function middleware(req: NextRequest) {
|
|||||||
|| pathname.startsWith("/cms-service")
|
|| pathname.startsWith("/cms-service")
|
||||||
|| pathname.startsWith("/user-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}`;
|
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")) {
|
if (pathname.startsWith("/dc-service")) {
|
||||||
|
|||||||
@@ -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");
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user