From 1862497bf48c476e5dcce72387590b4509d9a859 Mon Sep 17 00:00:00 2001 From: yschoi Date: Tue, 9 Sep 2025 10:38:11 +0900 Subject: [PATCH] =?UTF-8?q?api=20url=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/sn/.env.development | 4 +- apps/sn/.env.local | 12 +- apps/sn/.env.production | 8 +- .../map/components/popupComponent/smh.tsx | 2 +- .../map/searchModal/useSearchModal.tsx | 2 +- .../(with-base-layout)/ii/fileupload/page.tsx | 2 +- apps/sn/app/components/lib/api/index.ts | 2 +- .../app/components/lib/utils/fileDownload.ts | 1 - apps/sn/middleware.ts | 116 +++++++++--------- 9 files changed, 76 insertions(+), 73 deletions(-) diff --git a/apps/sn/.env.development b/apps/sn/.env.development index d137c4f9f..24edce282 100644 --- a/apps/sn/.env.development +++ b/apps/sn/.env.development @@ -8,6 +8,6 @@ NEXT_PUBLIC_PROXY_HOST = http://con.mind-one.co.kr:11302 NEXT_PUBLIC_SERVER_API_URL = http://dev.onasys.co.kr:8000 NEXT_PUBLIC_GEOSERVER_URL = https://hasudo.geo.rsonesoft.com/geoserver NEXT_PUBLIC_LX_GEOSERVER_URL = http://con.mind-one.co.kr:11306/geoserver -NEXT_PUBLIC_DC_URL = https://apigateway.apps.rsonesoft.com NEXT_PUBLIC_NGII_URL = https://map.ngii.go.kr/openapi/Gettile.do?apiKey=04trYP9_xwLAfALjwZ-B8g -NEXT_PUBLIC_SEWERAGE_API_URL=http://con.mind-one.co.kr:11083/sewerage-service/api \ No newline at end of file +NEXT_PUBLIC_DC_URL = https://apigateway.apps.rsonesoft.com +NEXT_PUBLIC_SEWERAGE_API_URL=http://con.mind-one.co.kr:11083 \ No newline at end of file diff --git a/apps/sn/.env.local b/apps/sn/.env.local index 375f25fd5..9d5804fc0 100644 --- a/apps/sn/.env.local +++ b/apps/sn/.env.local @@ -5,12 +5,12 @@ NEXT_PUBLIC_ACCESS_TOKEN = access-token NEXT_PUBLIC_REFRESH_TOKEN = refresh-token NEXT_PUBLIC_PORT = 3002 NEXT_PUBLIC_PROXY_HOST = http://localhost:3002 -NEXT_PUBLIC_SERVER_API_URL = http://dev.onasys.co.kr:8000 NEXT_PUBLIC_GEOSERVER_URL = https://hasudo.geo.rsonesoft.com/geoserver NEXT_PUBLIC_LX_GEOSERVER_URL = http://con.mind-one.co.kr:11306/geoserver -NEXT_PUBLIC_DC_URL = https://apigateway.apps.rsonesoft.com NEXT_PUBLIC_NGII_URL = https://map.ngii.go.kr/openapi/Gettile.do?apiKey=04trYP9_xwLAfALjwZ-B8g -NEXT_PUBLIC_SEWERAGE_API_URL=http://con.mind-one.co.kr:11083/sewerage-service/api -#NEXT_PUBLIC_SEWERAGE_API_URL=http://192.168.1.128:8883/sewerage-service/api -#NEXT_PUBLIC_SEWERAGE_API_URL=http://192.168.1.222:8883/sewerage-service/api -#NEXT_PUBLIC_SEWERAGE_API_URL=http://192.168.1.66:8883/sewerage-service/api \ No newline at end of file +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_DC_URL = https://apigateway.apps.rsonesoft.com +#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 \ No newline at end of file diff --git a/apps/sn/.env.production b/apps/sn/.env.production index 7d7a547eb..158f22aaf 100644 --- a/apps/sn/.env.production +++ b/apps/sn/.env.production @@ -5,9 +5,9 @@ NEXT_PUBLIC_ACCESS_TOKEN = access-token NEXT_PUBLIC_REFRESH_TOKEN = refresh-token NEXT_PUBLIC_PORT = 3000 NEXT_PUBLIC_PROXY_HOST = https://sn.hasuon.or.kr -NEXT_PUBLIC_SERVER_API_URL = http://apigateway.iipbs-dev.svc.cluster.local:8000 NEXT_PUBLIC_GEOSERVER_URL = http://172.29.143.87:8080/geoserver -NEXT_PUBLIC_LX_GEOSERVER_URL = http://172.29.143.87:8080/geoserver_swl -NEXT_PUBLIC_DC_URL = http://apigateway.iipbs-dev.svc.cluster.local:8000 +NEXT_PUBLIC_LX_GEOSERVER_URL = http://172.29.143.87:8080/geoserver_swl NEXT_PUBLIC_NGII_URL = http://10.98.25.94:18080/openapi/Gettile.do?apiKey=BDE2BEF39DAFEC293AB6730150F222AC -NEXT_PUBLIC_SEWERAGE_API_URL = https://apigateway.hasuon.or.kr/sewerage-service/api +NEXT_PUBLIC_SERVER_API_URL = http://apigateway.iipbs-was.svc.cluster.local:8000 +NEXT_PUBLIC_SEWERAGE_API_URL = http://apigateway.iipbs-was.svc.cluster.local:8000 +NEXT_PUBLIC_DC_URL = http://apigateway.iipbs-was.svc.cluster.local:8000 diff --git a/apps/sn/app/(map-layout)/map/components/popupComponent/smh.tsx b/apps/sn/app/(map-layout)/map/components/popupComponent/smh.tsx index 5d5365834..f19518ab1 100644 --- a/apps/sn/app/(map-layout)/map/components/popupComponent/smh.tsx +++ b/apps/sn/app/(map-layout)/map/components/popupComponent/smh.tsx @@ -5,7 +5,7 @@ import GisApp from "@common/business_components/ui/map/lib/gis.core"; // 상류관로 보기 함수 (FeatureClickEventPopup에서 사용) export async function searchUpperPpls(gisMap: any, fcltMngNo: any) { - const BASE_URL = process.env.NEXT_PUBLIC_SEWERAGE_API_URL || ""; + const BASE_URL = "/sewerage-service/api"; const res = await fetch(`${BASE_URL}/v1/fcltmhl/upperPpls/${fcltMngNo}`, { method: "GET", }); diff --git a/apps/sn/app/(map-layout)/map/searchModal/useSearchModal.tsx b/apps/sn/app/(map-layout)/map/searchModal/useSearchModal.tsx index 30e7c232a..74695a53f 100644 --- a/apps/sn/app/(map-layout)/map/searchModal/useSearchModal.tsx +++ b/apps/sn/app/(map-layout)/map/searchModal/useSearchModal.tsx @@ -21,7 +21,7 @@ import { swageMhlCqlFilters } from './swageMhl'; import { swagePmstnCqlFilters } from './swagePmstn'; import { stofcbrCqlFilters } from './stofcbr'; -const API_URL = `${process.env.NEXT_PUBLIC_SEWERAGE_API_URL}`; +const API_URL = "/sewerage-service/api"; export const OPERATION_TABLE_SIZE = 5; export interface SearchModalProps { diff --git a/apps/sn/app/(with-base-layout)/ii/fileupload/page.tsx b/apps/sn/app/(with-base-layout)/ii/fileupload/page.tsx index e72f7f4a5..29d7f464e 100644 --- a/apps/sn/app/(with-base-layout)/ii/fileupload/page.tsx +++ b/apps/sn/app/(with-base-layout)/ii/fileupload/page.tsx @@ -3,7 +3,7 @@ // FileUpload.js import React, { useState } from 'react'; import axios from 'axios'; -const SEWERAGE_URL = process.env.NEXT_PUBLIC_SEWERAGE_API_URL || ""; +const SEWERAGE_URL = "/sewerage-service/api"; function FileUpload() { const [file, setFile] = useState(null); diff --git a/apps/sn/app/components/lib/api/index.ts b/apps/sn/app/components/lib/api/index.ts index f70b0f3c0..0da6984a0 100644 --- a/apps/sn/app/components/lib/api/index.ts +++ b/apps/sn/app/components/lib/api/index.ts @@ -1,7 +1,7 @@ import { useEffect, useState } from "react"; import axios from 'axios'; -const BASE_URL = process.env.NEXT_PUBLIC_SEWERAGE_API_URL || ''; +const BASE_URL = '/sewerage-service/api'; export const getData = async (url: string): Promise => { const res = await fetch(url.startsWith('/') ? `${url}` : `${BASE_URL}/${url}`, { diff --git a/apps/sn/app/components/lib/utils/fileDownload.ts b/apps/sn/app/components/lib/utils/fileDownload.ts index 31fcfac76..79d337e3d 100644 --- a/apps/sn/app/components/lib/utils/fileDownload.ts +++ b/apps/sn/app/components/lib/utils/fileDownload.ts @@ -1,4 +1,3 @@ -const BASE_URL = process.env.NEXT_PUBLIC_SERVER_API_URL || ''; export const handleDownload = async (api:string, fileNm:string) => { try { diff --git a/apps/sn/middleware.ts b/apps/sn/middleware.ts index 6ddf29f9f..8a1a2e716 100644 --- a/apps/sn/middleware.ts +++ b/apps/sn/middleware.ts @@ -1,5 +1,4 @@ import { NextRequest, NextResponse } from "next/server"; -import path from "path"; const AUTH_USER_ID = process.env.NEXT_PUBLIC_AUTH_USER_ID || "token-id"; const CLAIM_NAME = process.env.NEXT_PUBLIC_CLAIM_NAME || "Authorization"; @@ -9,23 +8,48 @@ const GEOSERVER_URL = process.env.NEXT_PUBLIC_GEOSERVER_URL || ""; const LX_GEOSERVER_URL = process.env.NEXT_PUBLIC_LX_GEOSERVER_URL || ""; const DC_URL = process.env.NEXT_PUBLIC_DC_URL || ""; +/** 공통: URLSearchParams의 값을 decodeURIComponent 적용하여 querystring 생성 */ +function toDecodedQueryString(params: URLSearchParams): string { + const entries: string[][] = Array.from(params.entries()).map(([k, v]) => { + try { + return [k, decodeURIComponent(v)] as string[]; + } catch { + return [k, v] as string[]; + } + }); + return new URLSearchParams(entries).toString(); +} + +/** 공통: 요청 헤더에 쿠키 기반 인증 값 주입 */ +function buildAuthHeaders(req: NextRequest): Headers { + const requestHeaders = new Headers(req.headers); + const token = req.cookies.get(CLAIM_NAME)?.value; + const userId = req.cookies.get(AUTH_USER_ID)?.value; + if (token) requestHeaders.set(CLAIM_NAME, token); + if (userId) requestHeaders.set(AUTH_USER_ID, userId); + return requestHeaders; +} + +/** 공통: rewrite 응답 생성 (헤더 주입 여부 선택) */ +function rewriteWith(url: string, req: NextRequest, withAuth = false): NextResponse { + return withAuth + ? NextResponse.rewrite(new URL(url), { headers: buildAuthHeaders(req) }) + : NextResponse.rewrite(new URL(url)); +} + export function middleware(req: NextRequest) { console.log("Middleware 진입:", req.nextUrl.pathname); const pathname = req.nextUrl.pathname; const searchParams = req.nextUrl.searchParams; if (pathname.startsWith("/server")) { - - const decodedParams = Array.from(searchParams.entries()) - .map(([key, value]) => `${key}=${decodeURIComponent(value)}`) - .join("&"); - - const newUrl = `${SERVER_API_URL}${pathname.replace("/server", "")}${ - decodedParams ? `?${decodedParams}` : "" - }`; - return NextResponse.rewrite(new URL(newUrl)); + const decodedQuery = toDecodedQueryString(searchParams); + const newUrl = `${SERVER_API_URL}${pathname.replace("/server", "")}${decodedQuery ? `?${decodedQuery}` : "" + }`; + console.log(`[Middleware] Rewriting from '/server' path to: ${newUrl}`); + return rewriteWith(newUrl, req, true); } - + if (pathname.startsWith("/geoserver")) { let queryParams = searchParams.toString(); const typename = searchParams.get("TYPENAME"); @@ -57,66 +81,45 @@ export function middleware(req: NextRequest) { || typename == "hasudo:tb_wr_htdfl_fclt" //온배수시설 || typename == "hasudo:tb_wr_ruse_fclt_dmd_co" //수요처 || typename == "hasudo:tb_wr_tmpr_dmd_co" //잠재수요처 - ){ + ) { const url = req.nextUrl.clone(); - url.searchParams.set('TYPENAME', typename.replace("hasudo:","")); + url.searchParams.set('TYPENAME', typename.replace("hasudo:", "")); queryParams = url.searchParams.toString(); - newUrl = `${SEWERAGE_API_URL}/v1/map/geometry${queryParams ? `?${queryParams}` : ""}`; + newUrl = `${SEWERAGE_API_URL}/sewerage-service/api/v1/map/geometry${queryParams ? `?${queryParams}` : ""}`; } console.log(`[Middleware] Rewriting from '/geoserver' path to: ${newUrl}`); return NextResponse.rewrite(new URL(newUrl)); } - - if ( - pathname.startsWith("/attach-service") || - pathname.startsWith("/cms-service") + + if (pathname.startsWith("/attach-service") + || 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}`; - - 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, - }); + const decodedQuery = toDecodedQueryString(searchParams); + const newUrl = `${SERVER_API_URL}${pathname}${decodedQuery ? `?${decodedQuery}` : ""}`; + console.log(`[Middleware] Rewriting from '${pathname}' path to: ${newUrl}`); + return rewriteWith(newUrl, req, true); } - - if (pathname.startsWith("/user-service")) { - const requestHeaders = new Headers(req.headers); - const newUrl = `${SERVER_API_URL}${pathname}`; - console.log( - `[Middleware] Rewriting from '/user-service' path to: ${newUrl}`, - ); - return NextResponse.rewrite(new URL(newUrl), { - headers: requestHeaders, - }); - } - if (pathname.startsWith("/dc-service")) { - const requestHeaders = new Headers(req.headers); - const decodedParams = Array.from(searchParams.entries()) - .map(([key, value]) => `${key}=${decodeURIComponent(value)}`) - .join("&"); - - const newUrl = `${DC_URL}${pathname}${decodedParams ? `?${decodedParams}` : ""}`; - console.log( - `[Middleware] Rewriting from '/dc-service' path to: ${newUrl}`, - ); - return NextResponse.rewrite(new URL(newUrl), { - headers: requestHeaders, - }); + const decodedQuery = toDecodedQueryString(searchParams); + const newUrl = `${DC_URL}${pathname}${decodedQuery ? `?${decodedQuery}` : ""}`; + console.log(`[Middleware] Rewriting from '${pathname}' path to: ${newUrl}`); + return rewriteWith(newUrl, req, true); } + + if (pathname.startsWith("/sewerage-service")) { + const decodedQuery = toDecodedQueryString(searchParams); + const newUrl = `${SEWERAGE_API_URL}${pathname}${decodedQuery ? `?${decodedQuery}` : ""}`; + console.log(`[Middleware] Rewriting from '${pathname}' path to: ${newUrl}`); + return rewriteWith(newUrl, req, true); + } + return NextResponse.next(); } + export const config = { matcher: [ "/server/:path*", @@ -125,6 +128,7 @@ export const config = { "/user-service/:path*", "/cms-service/:path*", "/dc-service/:path*", + "/sewerage-service/:path*", ], };