sales-frontend-server-side-helper 0.0.42 → 0.0.43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api-route/index.cjs +12 -21
- package/dist/api-route/index.cjs.map +1 -1
- package/dist/api-route/index.d.cts +3 -2
- package/dist/api-route/index.d.ts +3 -2
- package/dist/api-route/index.js +12 -21
- package/dist/api-route/index.js.map +1 -1
- package/dist/config/index.cjs +1 -6
- package/dist/config/index.cjs.map +1 -1
- package/dist/config/index.js +1 -6
- package/dist/config/index.js.map +1 -1
- package/dist/middleware/index.cjs +32 -36
- package/dist/middleware/index.cjs.map +1 -1
- package/dist/middleware/index.d.cts +3 -2
- package/dist/middleware/index.d.ts +3 -2
- package/dist/middleware/index.js +33 -37
- package/dist/middleware/index.js.map +1 -1
- package/dist/{server-side-helper.types-Cp3VfyqT.d.cts → server-side-helper.types-DBOErcVd.d.cts} +2 -16
- package/dist/{server-side-helper.types-Cp3VfyqT.d.ts → server-side-helper.types-DBOErcVd.d.ts} +2 -16
- package/dist/utils/index.cjs +8 -24
- package/dist/utils/index.cjs.map +1 -1
- package/dist/utils/index.d.cts +3 -3
- package/dist/utils/index.d.ts +3 -3
- package/dist/utils/index.js +9 -24
- package/dist/utils/index.js.map +1 -1
- package/package.json +3 -3
package/dist/middleware/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server';
|
|
2
|
-
import { getFormFactorFromUserAgent, getEnvironmentFromHostname } from 'sales-frontend-utils';
|
|
2
|
+
import { getFormFactorFromUserAgent, getApiHostNameFromEnvironment, getEnvironmentFromHostname } from 'sales-frontend-utils';
|
|
3
|
+
import { requestAccessTokens } from 'sales-frontend-api/middleware';
|
|
3
4
|
|
|
4
5
|
// src/middleware/dsp-middleware.ts
|
|
5
6
|
|
|
@@ -54,30 +55,18 @@ var isResponsivePath = (pathname, responsivePaths = []) => {
|
|
|
54
55
|
return responsivePaths.some((path) => pathname.startsWith(path));
|
|
55
56
|
};
|
|
56
57
|
var isStaticAsset = (pathname) => {
|
|
58
|
+
if (pathname.startsWith("/api")) {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
57
61
|
if (pathname.startsWith("/_next") || pathname === "/favicon.ico") {
|
|
58
62
|
return true;
|
|
59
63
|
}
|
|
60
|
-
|
|
61
|
-
return staticExtensions.test(pathname);
|
|
62
|
-
};
|
|
63
|
-
var getTokensFromServer = async (request, tempToken) => {
|
|
64
|
-
const { accessToken } = parseCookies(request);
|
|
65
|
-
if (accessToken || !tempToken) {
|
|
66
|
-
return null;
|
|
67
|
-
}
|
|
68
|
-
console.log(`[DSP Middleware] \uC784\uC2DC \uD1A0\uD070 \uCC98\uB9AC:: ${tempToken ? "\uC788\uC74C" : "\uC5C6\uC74C"}`);
|
|
69
|
-
const apiUrl = `https://nxl-dsp-stg.hanwhalife.com/api/dat/v1/post/exchange/${tempToken}`;
|
|
70
|
-
console.log("\uC694\uCCAD URL::", apiUrl);
|
|
71
|
-
const response = await fetch(apiUrl, { method: "POST" });
|
|
72
|
-
const data = await response.json();
|
|
73
|
-
console.log(`[DSP Middleware] \uD1A0\uD070 \uBC1C\uAE09 \uC131\uACF5`, data);
|
|
74
|
-
return data;
|
|
64
|
+
return /\.[a-zA-Z0-9]+$/.test(pathname);
|
|
75
65
|
};
|
|
76
66
|
|
|
77
67
|
// src/config/cookie-config.ts
|
|
78
68
|
var COOKIE_DEFAULT_CONFIG = {
|
|
79
69
|
httpOnly: true,
|
|
80
|
-
maxAge: 60 * 60 * 24,
|
|
81
70
|
sameSite: "strict",
|
|
82
71
|
secure: true
|
|
83
72
|
};
|
|
@@ -85,9 +74,6 @@ var COOKIE_DEFAULT_CONFIG = {
|
|
|
85
74
|
// src/utils/cookie-utils.ts
|
|
86
75
|
var createResponseWithCookies = (response, request, cookieData) => {
|
|
87
76
|
const { hostname } = new URL(request.url);
|
|
88
|
-
console.log("[createResponseWithCookies] \uCFE0\uD0A4 \uC124\uC815 \uC2DC\uC791");
|
|
89
|
-
console.log("cookieData::", cookieData);
|
|
90
|
-
console.log("hostname::", hostname);
|
|
91
77
|
if (cookieData?.tokens?.tokenType) {
|
|
92
78
|
response.cookies.set({
|
|
93
79
|
name: "tokenType",
|
|
@@ -106,7 +92,9 @@ var createResponseWithCookies = (response, request, cookieData) => {
|
|
|
106
92
|
response.cookies.set({
|
|
107
93
|
name: "accessToken",
|
|
108
94
|
value: cookieData.tokens.accessToken,
|
|
109
|
-
...getDefaultCookieConfig(hostname)
|
|
95
|
+
...getDefaultCookieConfig(hostname),
|
|
96
|
+
//! middleware 커스텀헤더 세팅 불가로 일단 풀어 넣음
|
|
97
|
+
httpOnly: false
|
|
110
98
|
});
|
|
111
99
|
}
|
|
112
100
|
if (cookieData?.tokens?.refreshToken) {
|
|
@@ -120,8 +108,7 @@ var createResponseWithCookies = (response, request, cookieData) => {
|
|
|
120
108
|
response.cookies.set({
|
|
121
109
|
name: "formFactor",
|
|
122
110
|
value: cookieData.formFactor,
|
|
123
|
-
...getDefaultCookieConfig(hostname)
|
|
124
|
-
maxAge: 0
|
|
111
|
+
...getDefaultCookieConfig(hostname)
|
|
125
112
|
});
|
|
126
113
|
}
|
|
127
114
|
return response;
|
|
@@ -151,21 +138,12 @@ var handleAdaptiveProcessing = (request, config) => {
|
|
|
151
138
|
tokens: config?.cookieData?.tokens ?? null
|
|
152
139
|
});
|
|
153
140
|
};
|
|
154
|
-
var handleApiRequest = (request) => {
|
|
141
|
+
var handleApiRequest = async (request) => {
|
|
155
142
|
const { pathname } = request.nextUrl;
|
|
156
143
|
if (!pathname.startsWith("/api/")) {
|
|
157
144
|
return null;
|
|
158
145
|
}
|
|
159
|
-
|
|
160
|
-
const requestHeaders = new Headers(request.headers);
|
|
161
|
-
if (accessToken) {
|
|
162
|
-
requestHeaders.set("Authorization", `Bearer ${accessToken}`);
|
|
163
|
-
}
|
|
164
|
-
return NextResponse.next({
|
|
165
|
-
request: {
|
|
166
|
-
headers: requestHeaders
|
|
167
|
-
}
|
|
168
|
-
});
|
|
146
|
+
return NextResponse.next();
|
|
169
147
|
};
|
|
170
148
|
var handleDirectUrlAccess = (request, config) => {
|
|
171
149
|
const { pathname } = request.nextUrl;
|
|
@@ -198,6 +176,22 @@ var handleResponsivePaths = (request, config) => {
|
|
|
198
176
|
tokens: config?.cookieData?.tokens ?? null
|
|
199
177
|
});
|
|
200
178
|
};
|
|
179
|
+
var getTokensFromServer = async (request, tempToken, forceApiHostName) => {
|
|
180
|
+
const { accessToken } = parseCookies(request);
|
|
181
|
+
if (accessToken || !tempToken) {
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
console.log(`[DSP Middleware] \uC784\uC2DC \uD1A0\uD070 \uCC98\uB9AC:: ${tempToken ? "\uC788\uC74C" : "\uC5C6\uC74C"}`);
|
|
185
|
+
const data = await requestAccessTokens(tempToken, {
|
|
186
|
+
baseURL: getApiHostNameFromEnvironment(new URL(request.url).hostname, forceApiHostName)
|
|
187
|
+
});
|
|
188
|
+
if (data.isSuccess === false) {
|
|
189
|
+
console.error("[DSP Middleware] \uD1A0\uD070 \uBC1C\uAE09 \uC2E4\uD328");
|
|
190
|
+
throw new Error("\uD1A0\uD070 \uBC1C\uAE09 \uC2E4\uD328");
|
|
191
|
+
}
|
|
192
|
+
console.log(`[DSP Middleware] \uD1A0\uD070 \uBC1C\uAE09 \uC131\uACF5`, data);
|
|
193
|
+
return data;
|
|
194
|
+
};
|
|
201
195
|
|
|
202
196
|
// src/middleware/dsp-middleware.ts
|
|
203
197
|
var processDspMiddleware = async (request, config) => {
|
|
@@ -205,6 +199,9 @@ var processDspMiddleware = async (request, config) => {
|
|
|
205
199
|
if (isStaticAsset(pathname)) {
|
|
206
200
|
return NextResponse.next();
|
|
207
201
|
}
|
|
202
|
+
console.log(`[DSP Middleware] \uCC98\uB9AC \uC2DC\uC791:: ${request.url}`);
|
|
203
|
+
console.log(`[DSP Middleware] pathname:: ${pathname}`);
|
|
204
|
+
console.log("[DSP Middleware] hostname:: ", new URL(request.url).hostname);
|
|
208
205
|
let tokens;
|
|
209
206
|
try {
|
|
210
207
|
const tokensResponse = await getTokensFromServer(request, parseQueryParameters(request).tempToken);
|
|
@@ -213,9 +210,9 @@ var processDspMiddleware = async (request, config) => {
|
|
|
213
210
|
console.error(`[DSP Middleware] \uD1A0\uD070 \uD68D\uB4DD \uC2E4\uD328:: ${pathname}`, error);
|
|
214
211
|
tokens = null;
|
|
215
212
|
}
|
|
216
|
-
const apiResponse = handleApiRequest(request);
|
|
213
|
+
const apiResponse = await handleApiRequest(request);
|
|
217
214
|
if (apiResponse) {
|
|
218
|
-
console.log(`[DSP Middleware] API \uC694\uCCAD:: ${pathname}`);
|
|
215
|
+
console.log(`[DSP Middleware] API \uC694\uCCAD pathname:: ${pathname}`);
|
|
219
216
|
return apiResponse;
|
|
220
217
|
}
|
|
221
218
|
const externalInternalResponse = handleExternalInternalPaths(request, { cookieData: { tokens } });
|
|
@@ -253,7 +250,6 @@ var createMiddleware = (handlers, config) => {
|
|
|
253
250
|
return NextResponse.next();
|
|
254
251
|
};
|
|
255
252
|
};
|
|
256
|
-
//! test
|
|
257
253
|
|
|
258
254
|
export { createMiddleware, handleAdaptiveProcessing, handleApiRequest, handleDirectUrlAccess, handleExternalInternalPaths, handleResponsivePaths, processDspMiddleware };
|
|
259
255
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utils/parse-utils.ts","../../src/utils/middleware-utils.ts","../../src/config/cookie-config.ts","../../src/utils/cookie-utils.ts","../../src/middleware/handlers/handleAdaptiveProcessing.ts","../../src/middleware/handlers/handleApiRequest.ts","../../src/middleware/handlers/handleDirectUrlAccess.ts","../../src/middleware/handlers/handleExternalInternalPaths.ts","../../src/middleware/handlers/handleResponsivePaths.ts","../../src/middleware/dsp-middleware.ts","../../src/middleware/handlers/createMiddleware.ts"],"names":["NextResponse"],"mappings":"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","file":"index.js","sourcesContent":["import { NextRequest } from 'next/server';\n\n/**\n * 요청 헤더에 값 파싱\n * @param request\n * @returns\n */\nexport const parseRequestHeaders = (request: NextRequest) => {\n return {\n formFactor: request.headers.get('X-Channel-FormFactor')\n };\n};\n\n/**\n * 쿼리 스트링 값 파싱\n * @param request\n * @returns\n */\nexport const parseQueryParameters = (request: NextRequest) => {\n const { searchParams } = request.nextUrl;\n\n return {\n tempToken: searchParams.get('tempToken')\n };\n};\n\n/**\n * 요청 쿠키에 값 파싱\n * @param request\n * @returns\n */\nexport const parseCookies = (request: NextRequest) => {\n return {\n formFactor: request.cookies.get('formFactor')?.value,\n accessToken: request.cookies.get('accessToken')?.value\n };\n};\n","import { NextRequest } from 'next/server';\n\nimport { getFormFactorFromUserAgent } from 'sales-frontend-utils';\n\nimport { DspResponseDspTokenResponseDto } from '../server-side-helper.types';\n\nimport { parseCookies, parseRequestHeaders } from './parse-utils';\n\n/**\n * FormFactor에 따른 적응형 경로 변환\n * @param pathname\n * @param formFactor\n * @returns\n */\nexport const convertAdaptiveTargetPath = (pathname: string, formFactor: string) => {\n if (pathname === '/') {\n return pathname;\n }\n\n switch (formFactor) {\n case 'tablet':\n return `/tablet${pathname}`;\n case 'phone':\n case 'smartphone':\n return `/mobile${pathname}`;\n case 'desktop':\n default:\n return `/pc${pathname}`;\n }\n};\n\n/**\n * FormFactor 구하기\n * @param request\n * @returns\n */\nexport const getFormFactor = (request: NextRequest) => {\n const userAgent = request.headers.get('user-agent') || '';\n\n // 1순위: Custom Header\n const headerValue = parseRequestHeaders(request).formFactor;\n if (headerValue) {\n return headerValue;\n }\n\n // 2순위: Cookie\n const cookieValue = parseCookies(request).formFactor;\n if (cookieValue) {\n return cookieValue;\n }\n\n // 3순위: User-Agent 판단\n return getFormFactorFromUserAgent(userAgent);\n};\n\n/**\n * 반응형 전용 pathname 판단\n * @param pathname\n * @param responsivePaths\n * @returns\n */\nexport const isResponsivePath = (pathname: string, responsivePaths: string[] = []): boolean => {\n return responsivePaths.some((path) => pathname.startsWith(path));\n};\n\n/**\n * 정적 자원 체크 함수\n * @param pathname\n * @returns\n */\nexport const isStaticAsset = (pathname: string): boolean => {\n // _next 관련 파일들\n if (pathname.startsWith('/_next') || pathname === '/favicon.ico') {\n return true;\n }\n\n // 확장자로 정적 파일 체크\n const staticExtensions =\n /\\.(js|jsx|ts|tsx|css|scss|sass|less|svg|png|jpg|jpeg|gif|webp|ico|bmp|woff|woff2|ttf|eot|otf|json|xml|txt|pdf|zip|rar|mp4|mp3|wav|ogg)$/i;\n\n return staticExtensions.test(pathname);\n};\n\n////////////\n//! test\n////////////\nexport const getTokensFromServer = async (\n request: NextRequest,\n tempToken: string | null\n): Promise<DspResponseDspTokenResponseDto | null> => {\n const { accessToken } = parseCookies(request);\n\n if (accessToken || !tempToken) {\n return null;\n }\n\n console.log(`[DSP Middleware] 임시 토큰 처리:: ${tempToken ? '있음' : '없음'}`);\n\n //const apiUrl = `${request.nextUrl.origin}/v1/post/exchange/${tempToken}`;\n const apiUrl = `https://nxl-dsp-stg.hanwhalife.com/api/dat/v1/post/exchange/${tempToken}`;\n\n console.log('요청 URL::', apiUrl);\n\n const response = await fetch(apiUrl, { method: 'POST' });\n\n const data: DspResponseDspTokenResponseDto = await response.json();\n\n console.log(`[DSP Middleware] 토큰 발급 성공`, data);\n\n return data;\n};\n","export const COOKIE_DEFAULT_CONFIG = {\n httpOnly: true,\n maxAge: 60 * 60 * 24,\n sameSite: 'strict' as const,\n secure: true\n};\n","import { NextRequest, NextResponse } from 'next/server';\n\nimport { getEnvironmentFromHostname } from 'sales-frontend-utils';\n\nimport { COOKIE_DEFAULT_CONFIG } from '../config/cookie-config';\nimport { CookieData } from '../server-side-helper.types';\n\n/**\n * 쿠키 생성\n * @param response\n * @param cookieData\n * @returns\n */\nexport const createResponseWithCookies = (\n response: NextResponse,\n request: NextRequest,\n cookieData?: CookieData\n): NextResponse => {\n const { hostname } = new URL(request.url);\n\n console.log('[createResponseWithCookies] 쿠키 설정 시작');\n console.log('cookieData::', cookieData);\n console.log('hostname::', hostname);\n\n // 토큰타입\n if (cookieData?.tokens?.tokenType) {\n response.cookies.set({\n name: 'tokenType',\n value: cookieData.tokens.tokenType,\n ...getDefaultCookieConfig(hostname)\n });\n }\n\n // expiresIn\n if (cookieData?.tokens?.expiresIn) {\n response.cookies.set({\n name: 'expiresIn',\n value: String(cookieData.tokens.expiresIn),\n ...getDefaultCookieConfig(hostname)\n });\n }\n\n // 액세스 토큰 쿠키\n if (cookieData?.tokens?.accessToken) {\n response.cookies.set({\n name: 'accessToken',\n value: cookieData.tokens.accessToken,\n ...getDefaultCookieConfig(hostname)\n });\n }\n\n // 리프레시 토큰 쿠키\n if (cookieData?.tokens?.refreshToken) {\n response.cookies.set({\n name: 'refreshToken',\n value: cookieData.tokens.refreshToken,\n ...getDefaultCookieConfig(hostname)\n });\n }\n\n // FormFactor 쿠키\n if (cookieData?.formFactor) {\n response.cookies.set({\n name: 'formFactor',\n value: cookieData.formFactor,\n ...getDefaultCookieConfig(hostname),\n maxAge: 0\n });\n }\n\n return response;\n};\n\n/**\n * 환경에 따른 기본 쿠키 설정값 반환\n * @param hostname\n * @returns\n */\nconst getDefaultCookieConfig = (hostname: string) => {\n const environment = getEnvironmentFromHostname(hostname);\n\n if (environment !== 'prd') {\n return {\n ...COOKIE_DEFAULT_CONFIG,\n httpOnly: false,\n secure: false,\n sameSite: 'lax' as const\n };\n }\n\n return COOKIE_DEFAULT_CONFIG;\n};\n","import { NextRequest, NextResponse } from 'next/server';\n\nimport { MiddlewareHandler, MiddlewareConfig } from '../../server-side-helper.types';\nimport { createResponseWithCookies } from '../../utils/cookie-utils';\nimport { getFormFactor, convertAdaptiveTargetPath } from '../../utils/middleware-utils';\n\n/**\n * 적응형 경로 처리(rewrite 처리)\n * 단, 쿠키를 넘겨주면 쿠키 생성을 해줌\n * @param request\n * @param config\n * @returns\n */\nexport const handleAdaptiveProcessing: MiddlewareHandler = (request: NextRequest, config?: MiddlewareConfig) => {\n const { nextUrl } = request;\n const formFactor = getFormFactor(request);\n\n const rewrittenUrl = nextUrl.clone();\n rewrittenUrl.pathname = convertAdaptiveTargetPath(nextUrl.pathname, formFactor);\n\n console.log(`[DSP Middleware] ReWrite 처리:: ${rewrittenUrl.pathname}`);\n\n return createResponseWithCookies(NextResponse.rewrite(rewrittenUrl), request, {\n formFactor,\n tokens: config?.cookieData?.tokens ?? null\n });\n};\n","import { NextRequest, NextResponse } from 'next/server';\n\nimport { MiddlewareHandler } from '../../server-side-helper.types';\nimport { parseCookies } from '../../utils/parse-utils';\n\n/**\n * API 요청 처리\n * Cookie에 AccessToken이 있으면 Authorization 헤더에 셋팅을 담당하는 함수\n * Only api 요청만 처리\n * @param request\n * @returns\n */\nexport const handleApiRequest: MiddlewareHandler = (request: NextRequest) => {\n const { pathname } = request.nextUrl;\n\n if (!pathname.startsWith('/api/')) {\n // 처리하지 않음 (온니 api 요청만 처리)\n return null;\n }\n\n const { accessToken } = parseCookies(request);\n const requestHeaders = new Headers(request.headers);\n\n if (accessToken) {\n requestHeaders.set('Authorization', `Bearer ${accessToken}`);\n }\n\n return NextResponse.next({\n request: {\n headers: requestHeaders\n }\n });\n};\n","import { NextRequest, NextResponse } from 'next/server';\n\nimport { MiddlewareHandler, MiddlewareConfig } from '../../server-side-helper.types';\nimport { createResponseWithCookies } from '../../utils/cookie-utils';\n\n/**\n * 직접 URL 접근 처리\n * 직접 URL 입력한 경우 그대로 통과\n * 쿠키를 넘겨주면 쿠키 생성을 해줌\n * @param request\n * @param config\n * @returns\n */\nexport const handleDirectUrlAccess: MiddlewareHandler = (request: NextRequest, config?: MiddlewareConfig) => {\n const { pathname } = request.nextUrl;\n\n const directPaths = ['/tablet/', '/mobile/', '/pc/', '/responsive/'];\n\n if (directPaths.some((path) => pathname.startsWith(path))) {\n return createResponseWithCookies(NextResponse.next(), request, {\n tokens: config?.cookieData?.tokens ?? null\n });\n }\n\n return null;\n};\n","import { NextRequest, NextResponse } from 'next/server';\n\nimport { MiddlewareHandler, MiddlewareConfig } from '../../server-side-helper.types';\nimport { createResponseWithCookies } from '../../utils/cookie-utils';\n\n/**\n * External/Internal 경로 처리\n * 컨텍스트를 벗어난 페이지 처리(아무런 간섭을 받지 않음)\n * 단, 쿠키를 넘겨주면 쿠키 생성을 해줌\n * @param request\n * @param config\n * @returns\n */\nexport const handleExternalInternalPaths: MiddlewareHandler = (request: NextRequest, config?: MiddlewareConfig) => {\n const { pathname } = request.nextUrl;\n\n if (pathname.startsWith('/external') || pathname.startsWith('/internal')) {\n return createResponseWithCookies(NextResponse.next(), request, {\n tokens: config?.cookieData?.tokens ?? null\n });\n }\n\n return null;\n};\n","import { NextRequest, NextResponse } from 'next/server';\n\nimport { MiddlewareHandler, MiddlewareConfig } from '../../server-side-helper.types';\nimport { createResponseWithCookies } from '../../utils/cookie-utils';\nimport { isResponsivePath } from '../../utils/middleware-utils';\n\n/**\n * 반응형 경로 처리(rewrite 처리)\n * 단, 쿠키를 넘겨주면 쿠키 생성을 해줌\n * @param request\n * @param config\n * @returns\n */\nexport const handleResponsivePaths: MiddlewareHandler = (request: NextRequest, config?: MiddlewareConfig) => {\n const { nextUrl } = request;\n const { pathname } = nextUrl;\n\n if (!isResponsivePath(pathname, config?.responsivePaths)) {\n return null;\n }\n\n const rewrittenUrl = nextUrl.clone();\n rewrittenUrl.pathname = `/responsive${pathname}`;\n\n return createResponseWithCookies(NextResponse.rewrite(rewrittenUrl), request, {\n tokens: config?.cookieData?.tokens ?? null\n });\n};\n","import { NextRequest, NextResponse } from 'next/server';\n\nimport { MiddlewareConfig } from '../server-side-helper.types';\nimport { getTokensFromServer, isStaticAsset } from '../utils/middleware-utils';\nimport { parseQueryParameters } from '../utils/parse-utils';\n\nimport { handleAdaptiveProcessing } from './handlers/handleAdaptiveProcessing';\nimport { handleApiRequest } from './handlers/handleApiRequest';\nimport { handleDirectUrlAccess } from './handlers/handleDirectUrlAccess';\nimport { handleExternalInternalPaths } from './handlers/handleExternalInternalPaths';\nimport { handleResponsivePaths } from './handlers/handleResponsivePaths';\n\nexport const processDspMiddleware = async (request: NextRequest, config?: MiddlewareConfig): Promise<NextResponse> => {\n const { pathname } = request.nextUrl;\n //console.log(`[DSP Middleware] 처리 시작:: ${pathname}`);\n\n // 0. 정적 자원 체크(Skip)\n if (isStaticAsset(pathname)) {\n //console.log(`[DSP Middleware] 정적 자원 패스:: ${pathname}`);\n\n return NextResponse.next();\n }\n\n // 1. 토큰 받기 (임시토큰만 있으면)\n let tokens;\n try {\n const tokensResponse = await getTokensFromServer(request, parseQueryParameters(request).tempToken);\n tokens = tokensResponse?.data;\n } catch (error) {\n // 토큰 없이 계속 진행\n console.error(`[DSP Middleware] 토큰 획득 실패:: ${pathname}`, error);\n tokens = null;\n }\n\n // 2. API 요청 처리\n const apiResponse = handleApiRequest(request);\n if (apiResponse) {\n console.log(`[DSP Middleware] API 요청:: ${pathname}`);\n\n return apiResponse;\n }\n\n // 3. 외부/내부 경로 처리\n const externalInternalResponse = handleExternalInternalPaths(request, { cookieData: { tokens } });\n if (externalInternalResponse) {\n console.log(`[DSP Middleware] External/Internal 경로로 처리:: ${pathname}`);\n\n return externalInternalResponse;\n }\n\n // 4. 직접 적응형 URL 접근 처리\n const directUrlResponse = handleDirectUrlAccess(request, { cookieData: { tokens } });\n if (directUrlResponse) {\n console.log(`[DSP Middleware] 직접 URL 접근으로 처리:: ${pathname}`);\n\n return directUrlResponse;\n }\n\n // 5. 반응형 전용 경로 처리\n const responsivePathResponse = handleResponsivePaths(request, {\n cookieData: { tokens },\n responsivePaths: config?.responsivePaths\n });\n if (responsivePathResponse) {\n console.log(`[DSP Middleware] 반응형 경로로 처리:: ${pathname}`);\n\n return responsivePathResponse;\n }\n\n // 6. 적응형 경로 처리\n const adaptiveResponse = handleAdaptiveProcessing(request, { cookieData: { tokens } });\n if (adaptiveResponse) {\n return adaptiveResponse;\n }\n\n // 모든 핸들러가 null을 반환하면 기본 처리\n return NextResponse.next();\n};\n","import { NextRequest, NextResponse } from 'next/server';\n\nimport { MiddlewareHandler, MiddlewareConfig } from '../../server-side-helper.types';\n\n/**\n * 미들웨어 조립 함수\n * @param handlers\n * @param config\n * @returns\n */\nexport const createMiddleware = (handlers: MiddlewareHandler[], config?: MiddlewareConfig) => {\n return (request: NextRequest): NextResponse => {\n // 핸들러들을 순서대로 실행\n for (const handler of handlers) {\n const result = handler(request, config);\n if (result) {\n return result; // 첫 번째로 처리된 결과 반환\n }\n }\n\n // 모든 핸들러가 null을 반환하면 기본 처리\n return NextResponse.next();\n };\n};\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/utils/parse-utils.ts","../../src/utils/middleware-utils.ts","../../src/config/cookie-config.ts","../../src/utils/cookie-utils.ts","../../src/middleware/handlers/handleAdaptiveProcessing.ts","../../src/middleware/handlers/handleApiRequest.ts","../../src/middleware/handlers/handleDirectUrlAccess.ts","../../src/middleware/handlers/handleExternalInternalPaths.ts","../../src/middleware/handlers/handleResponsivePaths.ts","../../src/middleware/handlers/handleTokensFromServer.ts","../../src/middleware/dsp-middleware.ts","../../src/middleware/handlers/createMiddleware.ts"],"names":["NextResponse"],"mappings":"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","file":"index.js","sourcesContent":["import { NextRequest } from 'next/server';\n\n/**\n * 요청 헤더에 값 파싱\n * @param request\n * @returns\n */\nexport const parseRequestHeaders = (request: NextRequest) => {\n return {\n formFactor: request.headers.get('X-Channel-FormFactor')\n };\n};\n\n/**\n * 쿼리 스트링 값 파싱\n * @param request\n * @returns\n */\nexport const parseQueryParameters = (request: NextRequest) => {\n const { searchParams } = request.nextUrl;\n\n return {\n tempToken: searchParams.get('tempToken')\n };\n};\n\n/**\n * 요청 쿠키에 값 파싱\n * @param request\n * @returns\n */\nexport const parseCookies = (request: NextRequest) => {\n return {\n formFactor: request.cookies.get('formFactor')?.value,\n accessToken: request.cookies.get('accessToken')?.value\n };\n};\n","import { NextRequest } from 'next/server';\n\nimport { getFormFactorFromUserAgent } from 'sales-frontend-utils';\n\nimport { parseCookies, parseRequestHeaders } from './parse-utils';\n\n/**\n * FormFactor에 따른 적응형 경로 변환\n * @param pathname\n * @param formFactor\n * @returns\n */\nexport const convertAdaptiveTargetPath = (pathname: string, formFactor: string) => {\n if (pathname === '/') {\n return pathname;\n }\n\n switch (formFactor) {\n case 'tablet':\n return `/tablet${pathname}`;\n case 'phone':\n case 'smartphone':\n return `/mobile${pathname}`;\n case 'desktop':\n default:\n return `/pc${pathname}`;\n }\n};\n\n/**\n * FormFactor 구하기\n * @param request\n * @returns\n */\nexport const getFormFactor = (request: NextRequest) => {\n const userAgent = request.headers.get('user-agent') || '';\n\n // 1순위: Custom Header\n const headerValue = parseRequestHeaders(request).formFactor;\n if (headerValue) {\n return headerValue;\n }\n\n // 2순위: Cookie\n const cookieValue = parseCookies(request).formFactor;\n if (cookieValue) {\n return cookieValue;\n }\n\n // 3순위: User-Agent 판단\n return getFormFactorFromUserAgent(userAgent);\n};\n\n/**\n * 반응형 전용 pathname 판단\n * @param pathname\n * @param responsivePaths\n * @returns\n */\nexport const isResponsivePath = (pathname: string, responsivePaths: string[] = []): boolean => {\n return responsivePaths.some((path) => pathname.startsWith(path));\n};\n\n/**\n * 정적 자원 체크 함수\n * @param pathname\n * @returns\n */\nexport const isStaticAsset = (pathname: string): boolean => {\n // API 라우트는 제외\n if (pathname.startsWith('/api')) {\n return false;\n }\n\n // _next 관련 파일들\n if (pathname.startsWith('/_next') || pathname === '/favicon.ico') {\n return true;\n }\n\n // 확장자가 있으면 정적 자원\n return /\\.[a-zA-Z0-9]+$/.test(pathname);\n};\n","export const COOKIE_DEFAULT_CONFIG = {\n httpOnly: true,\n sameSite: 'strict' as const,\n secure: true\n};\n","import { NextRequest, NextResponse } from 'next/server';\n\nimport { getEnvironmentFromHostname } from 'sales-frontend-utils';\n\nimport { COOKIE_DEFAULT_CONFIG } from '../config/cookie-config';\nimport { CookieData } from '../server-side-helper.types';\n\n/**\n * 쿠키 생성\n * @param response\n * @param cookieData\n * @returns\n */\nexport const createResponseWithCookies = (\n response: NextResponse,\n request: NextRequest,\n cookieData?: CookieData\n): NextResponse => {\n const { hostname } = new URL(request.url);\n\n // 토큰타입\n if (cookieData?.tokens?.tokenType) {\n response.cookies.set({\n name: 'tokenType',\n value: cookieData.tokens.tokenType,\n ...getDefaultCookieConfig(hostname)\n });\n }\n\n // expiresIn\n if (cookieData?.tokens?.expiresIn) {\n response.cookies.set({\n name: 'expiresIn',\n value: String(cookieData.tokens.expiresIn),\n ...getDefaultCookieConfig(hostname)\n });\n }\n\n // 액세스 토큰 쿠키\n if (cookieData?.tokens?.accessToken) {\n response.cookies.set({\n name: 'accessToken',\n value: cookieData.tokens.accessToken,\n ...getDefaultCookieConfig(hostname),\n //! middleware 커스텀헤더 세팅 불가로 일단 풀어 넣음\n httpOnly: false\n });\n }\n\n // 리프레시 토큰 쿠키\n if (cookieData?.tokens?.refreshToken) {\n response.cookies.set({\n name: 'refreshToken',\n value: cookieData.tokens.refreshToken,\n ...getDefaultCookieConfig(hostname)\n });\n }\n\n // FormFactor 쿠키\n if (cookieData?.formFactor) {\n response.cookies.set({\n name: 'formFactor',\n value: cookieData.formFactor,\n ...getDefaultCookieConfig(hostname)\n });\n }\n\n return response;\n};\n\n/**\n * 환경에 따른 기본 쿠키 설정값 반환\n * @param hostname\n * @returns\n */\nconst getDefaultCookieConfig = (hostname: string) => {\n const environment = getEnvironmentFromHostname(hostname);\n\n if (environment !== 'prd') {\n return {\n ...COOKIE_DEFAULT_CONFIG,\n httpOnly: false,\n secure: false,\n sameSite: 'lax' as const\n };\n }\n\n return COOKIE_DEFAULT_CONFIG;\n};\n","import { NextRequest, NextResponse } from 'next/server';\n\nimport { MiddlewareHandler, MiddlewareConfig } from '../../server-side-helper.types';\nimport { createResponseWithCookies } from '../../utils/cookie-utils';\nimport { getFormFactor, convertAdaptiveTargetPath } from '../../utils/middleware-utils';\n\n/**\n * 적응형 경로 처리(rewrite 처리)\n * 단, 쿠키를 넘겨주면 쿠키 생성을 해줌\n * @param request\n * @param config\n * @returns\n */\nexport const handleAdaptiveProcessing: MiddlewareHandler = (request: NextRequest, config?: MiddlewareConfig) => {\n const { nextUrl } = request;\n const formFactor = getFormFactor(request);\n\n const rewrittenUrl = nextUrl.clone();\n rewrittenUrl.pathname = convertAdaptiveTargetPath(nextUrl.pathname, formFactor);\n\n console.log(`[DSP Middleware] ReWrite 처리:: ${rewrittenUrl.pathname}`);\n\n return createResponseWithCookies(NextResponse.rewrite(rewrittenUrl), request, {\n formFactor,\n tokens: config?.cookieData?.tokens ?? null\n });\n};\n","import { NextRequest, NextResponse } from 'next/server';\n\n/**\n * API 요청 처리\n * Cookie에 AccessToken이 있으면 Authorization 헤더에 셋팅을 담당하는 함수\n * Only api 요청만 처리\n * @param request\n * @returns\n */\nexport const handleApiRequest = async (request: NextRequest): Promise<NextResponse | null> => {\n const { pathname } = request.nextUrl;\n\n if (!pathname.startsWith('/api/')) {\n // 처리하지 않음 (온니 api 요청만 처리)\n return null;\n }\n\n return NextResponse.next();\n};\n","import { NextRequest, NextResponse } from 'next/server';\n\nimport { MiddlewareHandler, MiddlewareConfig } from '../../server-side-helper.types';\nimport { createResponseWithCookies } from '../../utils/cookie-utils';\n\n/**\n * 직접 URL 접근 처리\n * 직접 URL 입력한 경우 그대로 통과\n * 쿠키를 넘겨주면 쿠키 생성을 해줌\n * @param request\n * @param config\n * @returns\n */\nexport const handleDirectUrlAccess: MiddlewareHandler = (request: NextRequest, config?: MiddlewareConfig) => {\n const { pathname } = request.nextUrl;\n\n const directPaths = ['/tablet/', '/mobile/', '/pc/', '/responsive/'];\n\n if (directPaths.some((path) => pathname.startsWith(path))) {\n return createResponseWithCookies(NextResponse.next(), request, {\n tokens: config?.cookieData?.tokens ?? null\n });\n }\n\n return null;\n};\n","import { NextRequest, NextResponse } from 'next/server';\n\nimport { MiddlewareHandler, MiddlewareConfig } from '../../server-side-helper.types';\nimport { createResponseWithCookies } from '../../utils/cookie-utils';\n\n/**\n * External/Internal 경로 처리\n * 컨텍스트를 벗어난 페이지 처리(아무런 간섭을 받지 않음)\n * 단, 쿠키를 넘겨주면 쿠키 생성을 해줌\n * @param request\n * @param config\n * @returns\n */\nexport const handleExternalInternalPaths: MiddlewareHandler = (request: NextRequest, config?: MiddlewareConfig) => {\n const { pathname } = request.nextUrl;\n\n if (pathname.startsWith('/external') || pathname.startsWith('/internal')) {\n return createResponseWithCookies(NextResponse.next(), request, {\n tokens: config?.cookieData?.tokens ?? null\n });\n }\n\n return null;\n};\n","import { NextRequest, NextResponse } from 'next/server';\n\nimport { MiddlewareHandler, MiddlewareConfig } from '../../server-side-helper.types';\nimport { createResponseWithCookies } from '../../utils/cookie-utils';\nimport { isResponsivePath } from '../../utils/middleware-utils';\n\n/**\n * 반응형 경로 처리(rewrite 처리)\n * 단, 쿠키를 넘겨주면 쿠키 생성을 해줌\n * @param request\n * @param config\n * @returns\n */\nexport const handleResponsivePaths: MiddlewareHandler = (request: NextRequest, config?: MiddlewareConfig) => {\n const { nextUrl } = request;\n const { pathname } = nextUrl;\n\n if (!isResponsivePath(pathname, config?.responsivePaths)) {\n return null;\n }\n\n const rewrittenUrl = nextUrl.clone();\n rewrittenUrl.pathname = `/responsive${pathname}`;\n\n return createResponseWithCookies(NextResponse.rewrite(rewrittenUrl), request, {\n tokens: config?.cookieData?.tokens ?? null\n });\n};\n","import { NextRequest } from 'next/server';\n\nimport { requestAccessTokens, DspResponseDspTokenResponseDto } from 'sales-frontend-api/middleware';\nimport { getApiHostNameFromEnvironment } from 'sales-frontend-utils';\n\nimport { parseCookies } from '../../utils';\n\n/**\n * 임시토큰만 있을 경우 AT, RT를 발급받는다.\n * @param request\n * @param tempToken\n * @returns\n */\nexport const getTokensFromServer = async (\n request: NextRequest,\n tempToken: string | null,\n forceApiHostName?: string\n): Promise<DspResponseDspTokenResponseDto | null> => {\n const { accessToken } = parseCookies(request);\n\n if (accessToken || !tempToken) {\n return null;\n }\n\n console.log(`[DSP Middleware] 임시 토큰 처리:: ${tempToken ? '있음' : '없음'}`);\n\n const data = await requestAccessTokens(tempToken, {\n baseURL: getApiHostNameFromEnvironment(new URL(request.url).hostname, forceApiHostName)\n });\n\n if (data.isSuccess === false) {\n console.error('[DSP Middleware] 토큰 발급 실패');\n\n throw new Error('토큰 발급 실패');\n }\n\n console.log(`[DSP Middleware] 토큰 발급 성공`, data);\n\n return data;\n};\n","import { NextRequest, NextResponse } from 'next/server';\n\nimport { MiddlewareConfig } from '../server-side-helper.types';\nimport { isStaticAsset } from '../utils/middleware-utils';\nimport { parseQueryParameters } from '../utils/parse-utils';\n\nimport { handleAdaptiveProcessing } from './handlers/handleAdaptiveProcessing';\nimport { handleApiRequest } from './handlers/handleApiRequest';\nimport { handleDirectUrlAccess } from './handlers/handleDirectUrlAccess';\nimport { handleExternalInternalPaths } from './handlers/handleExternalInternalPaths';\nimport { handleResponsivePaths } from './handlers/handleResponsivePaths';\nimport { getTokensFromServer } from './handlers/handleTokensFromServer';\n\nexport const processDspMiddleware = async (request: NextRequest, config?: MiddlewareConfig): Promise<NextResponse> => {\n const { pathname } = request.nextUrl;\n\n // 0. 정적 자원 체크(Skip)\n if (isStaticAsset(pathname)) {\n return NextResponse.next();\n }\n\n console.log(`[DSP Middleware] 처리 시작:: ${request.url}`);\n console.log(`[DSP Middleware] pathname:: ${pathname}`);\n console.log('[DSP Middleware] hostname:: ', new URL(request.url).hostname);\n\n // 1. 토큰 받기 (임시토큰만 있으면)\n let tokens;\n try {\n const tokensResponse = await getTokensFromServer(request, parseQueryParameters(request).tempToken);\n tokens = tokensResponse?.data;\n } catch (error) {\n // 토큰 없이 계속 진행\n console.error(`[DSP Middleware] 토큰 획득 실패:: ${pathname}`, error);\n tokens = null;\n }\n\n // 2. API 요청 처리(by pass)\n const apiResponse = await handleApiRequest(request);\n if (apiResponse) {\n console.log(`[DSP Middleware] API 요청 pathname:: ${pathname}`);\n\n return apiResponse;\n }\n\n // 3. 외부/내부 경로 처리\n const externalInternalResponse = handleExternalInternalPaths(request, { cookieData: { tokens } });\n if (externalInternalResponse) {\n console.log(`[DSP Middleware] External/Internal 경로로 처리:: ${pathname}`);\n\n return externalInternalResponse;\n }\n\n // 4. 직접 적응형 URL 접근 처리\n const directUrlResponse = handleDirectUrlAccess(request, { cookieData: { tokens } });\n if (directUrlResponse) {\n console.log(`[DSP Middleware] 직접 URL 접근으로 처리:: ${pathname}`);\n\n return directUrlResponse;\n }\n\n // 5. 반응형 전용 경로 처리\n const responsivePathResponse = handleResponsivePaths(request, {\n cookieData: { tokens },\n responsivePaths: config?.responsivePaths\n });\n if (responsivePathResponse) {\n console.log(`[DSP Middleware] 반응형 경로로 처리:: ${pathname}`);\n\n return responsivePathResponse;\n }\n\n // 6. 적응형 경로 처리\n const adaptiveResponse = handleAdaptiveProcessing(request, { cookieData: { tokens } });\n if (adaptiveResponse) {\n return adaptiveResponse;\n }\n\n // 모든 핸들러가 null을 반환하면 기본 처리\n return NextResponse.next();\n};\n","import { NextRequest, NextResponse } from 'next/server';\n\nimport { MiddlewareHandler, MiddlewareConfig } from '../../server-side-helper.types';\n\n/**\n * 미들웨어 조립 함수\n * @param handlers\n * @param config\n * @returns\n */\nexport const createMiddleware = (handlers: MiddlewareHandler[], config?: MiddlewareConfig) => {\n return (request: NextRequest): NextResponse => {\n // 핸들러들을 순서대로 실행\n for (const handler of handlers) {\n const result = handler(request, config);\n if (result) {\n return result; // 첫 번째로 처리된 결과 반환\n }\n }\n\n // 모든 핸들러가 null을 반환하면 기본 처리\n return NextResponse.next();\n };\n};\n"]}
|
package/dist/{server-side-helper.types-Cp3VfyqT.d.cts → server-side-helper.types-DBOErcVd.d.cts}
RENAMED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { NextRequest, NextResponse } from 'next/server';
|
|
2
|
+
import { DspTokenResponseDto } from 'sales-frontend-api/middleware';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* 각 처리 로직을 독립적인 함수화
|
|
@@ -24,21 +25,6 @@ interface CookieData {
|
|
|
24
25
|
tokens?: DspTokenResponseDto | null;
|
|
25
26
|
formFactor?: string | null;
|
|
26
27
|
}
|
|
27
|
-
interface DspTokenResponseDto {
|
|
28
|
-
tokenType: string;
|
|
29
|
-
accessToken: string;
|
|
30
|
-
refreshToken: string;
|
|
31
|
-
expiresIn: number;
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* 토큰 관련 응답 타입
|
|
35
|
-
*/
|
|
36
|
-
interface DspResponseDspTokenResponseDto {
|
|
37
|
-
isSuccess: boolean;
|
|
38
|
-
code: string;
|
|
39
|
-
message: string;
|
|
40
|
-
data?: DspTokenResponseDto;
|
|
41
|
-
}
|
|
42
28
|
/**
|
|
43
29
|
* API 에러 응답 타입
|
|
44
30
|
*/
|
|
@@ -49,4 +35,4 @@ interface ApiErrorResponse {
|
|
|
49
35
|
data: null;
|
|
50
36
|
}
|
|
51
37
|
|
|
52
|
-
export type { ApiErrorResponse as A, CookieData as C,
|
|
38
|
+
export type { ApiErrorResponse as A, CookieData as C, MiddlewareConfig as M, RefreshTokensOptions as R, MiddlewareHandler as a };
|
package/dist/{server-side-helper.types-Cp3VfyqT.d.ts → server-side-helper.types-DBOErcVd.d.ts}
RENAMED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { NextRequest, NextResponse } from 'next/server';
|
|
2
|
+
import { DspTokenResponseDto } from 'sales-frontend-api/middleware';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* 각 처리 로직을 독립적인 함수화
|
|
@@ -24,21 +25,6 @@ interface CookieData {
|
|
|
24
25
|
tokens?: DspTokenResponseDto | null;
|
|
25
26
|
formFactor?: string | null;
|
|
26
27
|
}
|
|
27
|
-
interface DspTokenResponseDto {
|
|
28
|
-
tokenType: string;
|
|
29
|
-
accessToken: string;
|
|
30
|
-
refreshToken: string;
|
|
31
|
-
expiresIn: number;
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* 토큰 관련 응답 타입
|
|
35
|
-
*/
|
|
36
|
-
interface DspResponseDspTokenResponseDto {
|
|
37
|
-
isSuccess: boolean;
|
|
38
|
-
code: string;
|
|
39
|
-
message: string;
|
|
40
|
-
data?: DspTokenResponseDto;
|
|
41
|
-
}
|
|
42
28
|
/**
|
|
43
29
|
* API 에러 응답 타입
|
|
44
30
|
*/
|
|
@@ -49,4 +35,4 @@ interface ApiErrorResponse {
|
|
|
49
35
|
data: null;
|
|
50
36
|
}
|
|
51
37
|
|
|
52
|
-
export type { ApiErrorResponse as A, CookieData as C,
|
|
38
|
+
export type { ApiErrorResponse as A, CookieData as C, MiddlewareConfig as M, RefreshTokensOptions as R, MiddlewareHandler as a };
|
package/dist/utils/index.cjs
CHANGED
|
@@ -7,7 +7,6 @@ var salesFrontendUtils = require('sales-frontend-utils');
|
|
|
7
7
|
// src/config/cookie-config.ts
|
|
8
8
|
var COOKIE_DEFAULT_CONFIG = {
|
|
9
9
|
httpOnly: true,
|
|
10
|
-
maxAge: 60 * 60 * 24,
|
|
11
10
|
sameSite: "strict",
|
|
12
11
|
secure: true
|
|
13
12
|
};
|
|
@@ -15,9 +14,6 @@ var COOKIE_DEFAULT_CONFIG = {
|
|
|
15
14
|
// src/utils/cookie-utils.ts
|
|
16
15
|
var createResponseWithCookies = (response, request, cookieData) => {
|
|
17
16
|
const { hostname } = new URL(request.url);
|
|
18
|
-
console.log("[createResponseWithCookies] \uCFE0\uD0A4 \uC124\uC815 \uC2DC\uC791");
|
|
19
|
-
console.log("cookieData::", cookieData);
|
|
20
|
-
console.log("hostname::", hostname);
|
|
21
17
|
if (cookieData?.tokens?.tokenType) {
|
|
22
18
|
response.cookies.set({
|
|
23
19
|
name: "tokenType",
|
|
@@ -36,7 +32,9 @@ var createResponseWithCookies = (response, request, cookieData) => {
|
|
|
36
32
|
response.cookies.set({
|
|
37
33
|
name: "accessToken",
|
|
38
34
|
value: cookieData.tokens.accessToken,
|
|
39
|
-
...getDefaultCookieConfig(hostname)
|
|
35
|
+
...getDefaultCookieConfig(hostname),
|
|
36
|
+
//! middleware 커스텀헤더 세팅 불가로 일단 풀어 넣음
|
|
37
|
+
httpOnly: false
|
|
40
38
|
});
|
|
41
39
|
}
|
|
42
40
|
if (cookieData?.tokens?.refreshToken) {
|
|
@@ -50,8 +48,7 @@ var createResponseWithCookies = (response, request, cookieData) => {
|
|
|
50
48
|
response.cookies.set({
|
|
51
49
|
name: "formFactor",
|
|
52
50
|
value: cookieData.formFactor,
|
|
53
|
-
...getDefaultCookieConfig(hostname)
|
|
54
|
-
maxAge: 0
|
|
51
|
+
...getDefaultCookieConfig(hostname)
|
|
55
52
|
});
|
|
56
53
|
}
|
|
57
54
|
return response;
|
|
@@ -120,31 +117,18 @@ var isResponsivePath = (pathname, responsivePaths = []) => {
|
|
|
120
117
|
return responsivePaths.some((path) => pathname.startsWith(path));
|
|
121
118
|
};
|
|
122
119
|
var isStaticAsset = (pathname) => {
|
|
120
|
+
if (pathname.startsWith("/api")) {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
123
|
if (pathname.startsWith("/_next") || pathname === "/favicon.ico") {
|
|
124
124
|
return true;
|
|
125
125
|
}
|
|
126
|
-
|
|
127
|
-
return staticExtensions.test(pathname);
|
|
128
|
-
};
|
|
129
|
-
var getTokensFromServer = async (request, tempToken) => {
|
|
130
|
-
const { accessToken } = parseCookies(request);
|
|
131
|
-
if (accessToken || !tempToken) {
|
|
132
|
-
return null;
|
|
133
|
-
}
|
|
134
|
-
console.log(`[DSP Middleware] \uC784\uC2DC \uD1A0\uD070 \uCC98\uB9AC:: ${tempToken ? "\uC788\uC74C" : "\uC5C6\uC74C"}`);
|
|
135
|
-
const apiUrl = `https://nxl-dsp-stg.hanwhalife.com/api/dat/v1/post/exchange/${tempToken}`;
|
|
136
|
-
console.log("\uC694\uCCAD URL::", apiUrl);
|
|
137
|
-
const response = await fetch(apiUrl, { method: "POST" });
|
|
138
|
-
const data = await response.json();
|
|
139
|
-
console.log(`[DSP Middleware] \uD1A0\uD070 \uBC1C\uAE09 \uC131\uACF5`, data);
|
|
140
|
-
return data;
|
|
126
|
+
return /\.[a-zA-Z0-9]+$/.test(pathname);
|
|
141
127
|
};
|
|
142
|
-
//! test
|
|
143
128
|
|
|
144
129
|
exports.convertAdaptiveTargetPath = convertAdaptiveTargetPath;
|
|
145
130
|
exports.createResponseWithCookies = createResponseWithCookies;
|
|
146
131
|
exports.getFormFactor = getFormFactor;
|
|
147
|
-
exports.getTokensFromServer = getTokensFromServer;
|
|
148
132
|
exports.isResponsivePath = isResponsivePath;
|
|
149
133
|
exports.isStaticAsset = isStaticAsset;
|
|
150
134
|
exports.parseCookies = parseCookies;
|
package/dist/utils/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/config/cookie-config.ts","../../src/utils/cookie-utils.ts","../../src/utils/parse-utils.ts","../../src/utils/middleware-utils.ts"],"names":["getEnvironmentFromHostname","getFormFactorFromUserAgent"],"mappings":";;;;;;;AAAO,IAAM,qBAAwB,GAAA;AAAA,EACnC,QAAU,EAAA,IAAA;AAAA,EACV,
|
|
1
|
+
{"version":3,"sources":["../../src/config/cookie-config.ts","../../src/utils/cookie-utils.ts","../../src/utils/parse-utils.ts","../../src/utils/middleware-utils.ts"],"names":["getEnvironmentFromHostname","getFormFactorFromUserAgent"],"mappings":"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","file":"index.cjs","sourcesContent":["export const COOKIE_DEFAULT_CONFIG = {\n httpOnly: true,\n sameSite: 'strict' as const,\n secure: true\n};\n","import { NextRequest, NextResponse } from 'next/server';\n\nimport { getEnvironmentFromHostname } from 'sales-frontend-utils';\n\nimport { COOKIE_DEFAULT_CONFIG } from '../config/cookie-config';\nimport { CookieData } from '../server-side-helper.types';\n\n/**\n * 쿠키 생성\n * @param response\n * @param cookieData\n * @returns\n */\nexport const createResponseWithCookies = (\n response: NextResponse,\n request: NextRequest,\n cookieData?: CookieData\n): NextResponse => {\n const { hostname } = new URL(request.url);\n\n // 토큰타입\n if (cookieData?.tokens?.tokenType) {\n response.cookies.set({\n name: 'tokenType',\n value: cookieData.tokens.tokenType,\n ...getDefaultCookieConfig(hostname)\n });\n }\n\n // expiresIn\n if (cookieData?.tokens?.expiresIn) {\n response.cookies.set({\n name: 'expiresIn',\n value: String(cookieData.tokens.expiresIn),\n ...getDefaultCookieConfig(hostname)\n });\n }\n\n // 액세스 토큰 쿠키\n if (cookieData?.tokens?.accessToken) {\n response.cookies.set({\n name: 'accessToken',\n value: cookieData.tokens.accessToken,\n ...getDefaultCookieConfig(hostname),\n //! middleware 커스텀헤더 세팅 불가로 일단 풀어 넣음\n httpOnly: false\n });\n }\n\n // 리프레시 토큰 쿠키\n if (cookieData?.tokens?.refreshToken) {\n response.cookies.set({\n name: 'refreshToken',\n value: cookieData.tokens.refreshToken,\n ...getDefaultCookieConfig(hostname)\n });\n }\n\n // FormFactor 쿠키\n if (cookieData?.formFactor) {\n response.cookies.set({\n name: 'formFactor',\n value: cookieData.formFactor,\n ...getDefaultCookieConfig(hostname)\n });\n }\n\n return response;\n};\n\n/**\n * 환경에 따른 기본 쿠키 설정값 반환\n * @param hostname\n * @returns\n */\nconst getDefaultCookieConfig = (hostname: string) => {\n const environment = getEnvironmentFromHostname(hostname);\n\n if (environment !== 'prd') {\n return {\n ...COOKIE_DEFAULT_CONFIG,\n httpOnly: false,\n secure: false,\n sameSite: 'lax' as const\n };\n }\n\n return COOKIE_DEFAULT_CONFIG;\n};\n","import { NextRequest } from 'next/server';\n\n/**\n * 요청 헤더에 값 파싱\n * @param request\n * @returns\n */\nexport const parseRequestHeaders = (request: NextRequest) => {\n return {\n formFactor: request.headers.get('X-Channel-FormFactor')\n };\n};\n\n/**\n * 쿼리 스트링 값 파싱\n * @param request\n * @returns\n */\nexport const parseQueryParameters = (request: NextRequest) => {\n const { searchParams } = request.nextUrl;\n\n return {\n tempToken: searchParams.get('tempToken')\n };\n};\n\n/**\n * 요청 쿠키에 값 파싱\n * @param request\n * @returns\n */\nexport const parseCookies = (request: NextRequest) => {\n return {\n formFactor: request.cookies.get('formFactor')?.value,\n accessToken: request.cookies.get('accessToken')?.value\n };\n};\n","import { NextRequest } from 'next/server';\n\nimport { getFormFactorFromUserAgent } from 'sales-frontend-utils';\n\nimport { parseCookies, parseRequestHeaders } from './parse-utils';\n\n/**\n * FormFactor에 따른 적응형 경로 변환\n * @param pathname\n * @param formFactor\n * @returns\n */\nexport const convertAdaptiveTargetPath = (pathname: string, formFactor: string) => {\n if (pathname === '/') {\n return pathname;\n }\n\n switch (formFactor) {\n case 'tablet':\n return `/tablet${pathname}`;\n case 'phone':\n case 'smartphone':\n return `/mobile${pathname}`;\n case 'desktop':\n default:\n return `/pc${pathname}`;\n }\n};\n\n/**\n * FormFactor 구하기\n * @param request\n * @returns\n */\nexport const getFormFactor = (request: NextRequest) => {\n const userAgent = request.headers.get('user-agent') || '';\n\n // 1순위: Custom Header\n const headerValue = parseRequestHeaders(request).formFactor;\n if (headerValue) {\n return headerValue;\n }\n\n // 2순위: Cookie\n const cookieValue = parseCookies(request).formFactor;\n if (cookieValue) {\n return cookieValue;\n }\n\n // 3순위: User-Agent 판단\n return getFormFactorFromUserAgent(userAgent);\n};\n\n/**\n * 반응형 전용 pathname 판단\n * @param pathname\n * @param responsivePaths\n * @returns\n */\nexport const isResponsivePath = (pathname: string, responsivePaths: string[] = []): boolean => {\n return responsivePaths.some((path) => pathname.startsWith(path));\n};\n\n/**\n * 정적 자원 체크 함수\n * @param pathname\n * @returns\n */\nexport const isStaticAsset = (pathname: string): boolean => {\n // API 라우트는 제외\n if (pathname.startsWith('/api')) {\n return false;\n }\n\n // _next 관련 파일들\n if (pathname.startsWith('/_next') || pathname === '/favicon.ico') {\n return true;\n }\n\n // 확장자가 있으면 정적 자원\n return /\\.[a-zA-Z0-9]+$/.test(pathname);\n};\n"]}
|
package/dist/utils/index.d.cts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { NextResponse, NextRequest } from 'next/server';
|
|
2
|
-
import { C as CookieData
|
|
2
|
+
import { C as CookieData } from '../server-side-helper.types-DBOErcVd.cjs';
|
|
3
|
+
import 'sales-frontend-api/middleware';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* 쿠키 생성
|
|
@@ -35,7 +36,6 @@ declare const isResponsivePath: (pathname: string, responsivePaths?: string[]) =
|
|
|
35
36
|
* @returns
|
|
36
37
|
*/
|
|
37
38
|
declare const isStaticAsset: (pathname: string) => boolean;
|
|
38
|
-
declare const getTokensFromServer: (request: NextRequest, tempToken: string | null) => Promise<DspResponseDspTokenResponseDto | null>;
|
|
39
39
|
|
|
40
40
|
/**
|
|
41
41
|
* 요청 헤더에 값 파싱
|
|
@@ -63,4 +63,4 @@ declare const parseCookies: (request: NextRequest) => {
|
|
|
63
63
|
accessToken: string | undefined;
|
|
64
64
|
};
|
|
65
65
|
|
|
66
|
-
export { convertAdaptiveTargetPath, createResponseWithCookies, getFormFactor,
|
|
66
|
+
export { convertAdaptiveTargetPath, createResponseWithCookies, getFormFactor, isResponsivePath, isStaticAsset, parseCookies, parseQueryParameters, parseRequestHeaders };
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { NextResponse, NextRequest } from 'next/server';
|
|
2
|
-
import { C as CookieData
|
|
2
|
+
import { C as CookieData } from '../server-side-helper.types-DBOErcVd.js';
|
|
3
|
+
import 'sales-frontend-api/middleware';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* 쿠키 생성
|
|
@@ -35,7 +36,6 @@ declare const isResponsivePath: (pathname: string, responsivePaths?: string[]) =
|
|
|
35
36
|
* @returns
|
|
36
37
|
*/
|
|
37
38
|
declare const isStaticAsset: (pathname: string) => boolean;
|
|
38
|
-
declare const getTokensFromServer: (request: NextRequest, tempToken: string | null) => Promise<DspResponseDspTokenResponseDto | null>;
|
|
39
39
|
|
|
40
40
|
/**
|
|
41
41
|
* 요청 헤더에 값 파싱
|
|
@@ -63,4 +63,4 @@ declare const parseCookies: (request: NextRequest) => {
|
|
|
63
63
|
accessToken: string | undefined;
|
|
64
64
|
};
|
|
65
65
|
|
|
66
|
-
export { convertAdaptiveTargetPath, createResponseWithCookies, getFormFactor,
|
|
66
|
+
export { convertAdaptiveTargetPath, createResponseWithCookies, getFormFactor, isResponsivePath, isStaticAsset, parseCookies, parseQueryParameters, parseRequestHeaders };
|
package/dist/utils/index.js
CHANGED
|
@@ -5,7 +5,6 @@ import { getEnvironmentFromHostname, getFormFactorFromUserAgent } from 'sales-fr
|
|
|
5
5
|
// src/config/cookie-config.ts
|
|
6
6
|
var COOKIE_DEFAULT_CONFIG = {
|
|
7
7
|
httpOnly: true,
|
|
8
|
-
maxAge: 60 * 60 * 24,
|
|
9
8
|
sameSite: "strict",
|
|
10
9
|
secure: true
|
|
11
10
|
};
|
|
@@ -13,9 +12,6 @@ var COOKIE_DEFAULT_CONFIG = {
|
|
|
13
12
|
// src/utils/cookie-utils.ts
|
|
14
13
|
var createResponseWithCookies = (response, request, cookieData) => {
|
|
15
14
|
const { hostname } = new URL(request.url);
|
|
16
|
-
console.log("[createResponseWithCookies] \uCFE0\uD0A4 \uC124\uC815 \uC2DC\uC791");
|
|
17
|
-
console.log("cookieData::", cookieData);
|
|
18
|
-
console.log("hostname::", hostname);
|
|
19
15
|
if (cookieData?.tokens?.tokenType) {
|
|
20
16
|
response.cookies.set({
|
|
21
17
|
name: "tokenType",
|
|
@@ -34,7 +30,9 @@ var createResponseWithCookies = (response, request, cookieData) => {
|
|
|
34
30
|
response.cookies.set({
|
|
35
31
|
name: "accessToken",
|
|
36
32
|
value: cookieData.tokens.accessToken,
|
|
37
|
-
...getDefaultCookieConfig(hostname)
|
|
33
|
+
...getDefaultCookieConfig(hostname),
|
|
34
|
+
//! middleware 커스텀헤더 세팅 불가로 일단 풀어 넣음
|
|
35
|
+
httpOnly: false
|
|
38
36
|
});
|
|
39
37
|
}
|
|
40
38
|
if (cookieData?.tokens?.refreshToken) {
|
|
@@ -48,8 +46,7 @@ var createResponseWithCookies = (response, request, cookieData) => {
|
|
|
48
46
|
response.cookies.set({
|
|
49
47
|
name: "formFactor",
|
|
50
48
|
value: cookieData.formFactor,
|
|
51
|
-
...getDefaultCookieConfig(hostname)
|
|
52
|
-
maxAge: 0
|
|
49
|
+
...getDefaultCookieConfig(hostname)
|
|
53
50
|
});
|
|
54
51
|
}
|
|
55
52
|
return response;
|
|
@@ -118,27 +115,15 @@ var isResponsivePath = (pathname, responsivePaths = []) => {
|
|
|
118
115
|
return responsivePaths.some((path) => pathname.startsWith(path));
|
|
119
116
|
};
|
|
120
117
|
var isStaticAsset = (pathname) => {
|
|
118
|
+
if (pathname.startsWith("/api")) {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
121
|
if (pathname.startsWith("/_next") || pathname === "/favicon.ico") {
|
|
122
122
|
return true;
|
|
123
123
|
}
|
|
124
|
-
|
|
125
|
-
return staticExtensions.test(pathname);
|
|
126
|
-
};
|
|
127
|
-
var getTokensFromServer = async (request, tempToken) => {
|
|
128
|
-
const { accessToken } = parseCookies(request);
|
|
129
|
-
if (accessToken || !tempToken) {
|
|
130
|
-
return null;
|
|
131
|
-
}
|
|
132
|
-
console.log(`[DSP Middleware] \uC784\uC2DC \uD1A0\uD070 \uCC98\uB9AC:: ${tempToken ? "\uC788\uC74C" : "\uC5C6\uC74C"}`);
|
|
133
|
-
const apiUrl = `https://nxl-dsp-stg.hanwhalife.com/api/dat/v1/post/exchange/${tempToken}`;
|
|
134
|
-
console.log("\uC694\uCCAD URL::", apiUrl);
|
|
135
|
-
const response = await fetch(apiUrl, { method: "POST" });
|
|
136
|
-
const data = await response.json();
|
|
137
|
-
console.log(`[DSP Middleware] \uD1A0\uD070 \uBC1C\uAE09 \uC131\uACF5`, data);
|
|
138
|
-
return data;
|
|
124
|
+
return /\.[a-zA-Z0-9]+$/.test(pathname);
|
|
139
125
|
};
|
|
140
|
-
//! test
|
|
141
126
|
|
|
142
|
-
export { convertAdaptiveTargetPath, createResponseWithCookies, getFormFactor,
|
|
127
|
+
export { convertAdaptiveTargetPath, createResponseWithCookies, getFormFactor, isResponsivePath, isStaticAsset, parseCookies, parseQueryParameters, parseRequestHeaders };
|
|
143
128
|
//# sourceMappingURL=index.js.map
|
|
144
129
|
//# sourceMappingURL=index.js.map
|
package/dist/utils/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/config/cookie-config.ts","../../src/utils/cookie-utils.ts","../../src/utils/parse-utils.ts","../../src/utils/middleware-utils.ts"],"names":[],"mappings":";;;;;AAAO,IAAM,qBAAwB,GAAA;AAAA,EACnC,QAAU,EAAA,IAAA;AAAA,EACV,
|
|
1
|
+
{"version":3,"sources":["../../src/config/cookie-config.ts","../../src/utils/cookie-utils.ts","../../src/utils/parse-utils.ts","../../src/utils/middleware-utils.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["export const COOKIE_DEFAULT_CONFIG = {\n httpOnly: true,\n sameSite: 'strict' as const,\n secure: true\n};\n","import { NextRequest, NextResponse } from 'next/server';\n\nimport { getEnvironmentFromHostname } from 'sales-frontend-utils';\n\nimport { COOKIE_DEFAULT_CONFIG } from '../config/cookie-config';\nimport { CookieData } from '../server-side-helper.types';\n\n/**\n * 쿠키 생성\n * @param response\n * @param cookieData\n * @returns\n */\nexport const createResponseWithCookies = (\n response: NextResponse,\n request: NextRequest,\n cookieData?: CookieData\n): NextResponse => {\n const { hostname } = new URL(request.url);\n\n // 토큰타입\n if (cookieData?.tokens?.tokenType) {\n response.cookies.set({\n name: 'tokenType',\n value: cookieData.tokens.tokenType,\n ...getDefaultCookieConfig(hostname)\n });\n }\n\n // expiresIn\n if (cookieData?.tokens?.expiresIn) {\n response.cookies.set({\n name: 'expiresIn',\n value: String(cookieData.tokens.expiresIn),\n ...getDefaultCookieConfig(hostname)\n });\n }\n\n // 액세스 토큰 쿠키\n if (cookieData?.tokens?.accessToken) {\n response.cookies.set({\n name: 'accessToken',\n value: cookieData.tokens.accessToken,\n ...getDefaultCookieConfig(hostname),\n //! middleware 커스텀헤더 세팅 불가로 일단 풀어 넣음\n httpOnly: false\n });\n }\n\n // 리프레시 토큰 쿠키\n if (cookieData?.tokens?.refreshToken) {\n response.cookies.set({\n name: 'refreshToken',\n value: cookieData.tokens.refreshToken,\n ...getDefaultCookieConfig(hostname)\n });\n }\n\n // FormFactor 쿠키\n if (cookieData?.formFactor) {\n response.cookies.set({\n name: 'formFactor',\n value: cookieData.formFactor,\n ...getDefaultCookieConfig(hostname)\n });\n }\n\n return response;\n};\n\n/**\n * 환경에 따른 기본 쿠키 설정값 반환\n * @param hostname\n * @returns\n */\nconst getDefaultCookieConfig = (hostname: string) => {\n const environment = getEnvironmentFromHostname(hostname);\n\n if (environment !== 'prd') {\n return {\n ...COOKIE_DEFAULT_CONFIG,\n httpOnly: false,\n secure: false,\n sameSite: 'lax' as const\n };\n }\n\n return COOKIE_DEFAULT_CONFIG;\n};\n","import { NextRequest } from 'next/server';\n\n/**\n * 요청 헤더에 값 파싱\n * @param request\n * @returns\n */\nexport const parseRequestHeaders = (request: NextRequest) => {\n return {\n formFactor: request.headers.get('X-Channel-FormFactor')\n };\n};\n\n/**\n * 쿼리 스트링 값 파싱\n * @param request\n * @returns\n */\nexport const parseQueryParameters = (request: NextRequest) => {\n const { searchParams } = request.nextUrl;\n\n return {\n tempToken: searchParams.get('tempToken')\n };\n};\n\n/**\n * 요청 쿠키에 값 파싱\n * @param request\n * @returns\n */\nexport const parseCookies = (request: NextRequest) => {\n return {\n formFactor: request.cookies.get('formFactor')?.value,\n accessToken: request.cookies.get('accessToken')?.value\n };\n};\n","import { NextRequest } from 'next/server';\n\nimport { getFormFactorFromUserAgent } from 'sales-frontend-utils';\n\nimport { parseCookies, parseRequestHeaders } from './parse-utils';\n\n/**\n * FormFactor에 따른 적응형 경로 변환\n * @param pathname\n * @param formFactor\n * @returns\n */\nexport const convertAdaptiveTargetPath = (pathname: string, formFactor: string) => {\n if (pathname === '/') {\n return pathname;\n }\n\n switch (formFactor) {\n case 'tablet':\n return `/tablet${pathname}`;\n case 'phone':\n case 'smartphone':\n return `/mobile${pathname}`;\n case 'desktop':\n default:\n return `/pc${pathname}`;\n }\n};\n\n/**\n * FormFactor 구하기\n * @param request\n * @returns\n */\nexport const getFormFactor = (request: NextRequest) => {\n const userAgent = request.headers.get('user-agent') || '';\n\n // 1순위: Custom Header\n const headerValue = parseRequestHeaders(request).formFactor;\n if (headerValue) {\n return headerValue;\n }\n\n // 2순위: Cookie\n const cookieValue = parseCookies(request).formFactor;\n if (cookieValue) {\n return cookieValue;\n }\n\n // 3순위: User-Agent 판단\n return getFormFactorFromUserAgent(userAgent);\n};\n\n/**\n * 반응형 전용 pathname 판단\n * @param pathname\n * @param responsivePaths\n * @returns\n */\nexport const isResponsivePath = (pathname: string, responsivePaths: string[] = []): boolean => {\n return responsivePaths.some((path) => pathname.startsWith(path));\n};\n\n/**\n * 정적 자원 체크 함수\n * @param pathname\n * @returns\n */\nexport const isStaticAsset = (pathname: string): boolean => {\n // API 라우트는 제외\n if (pathname.startsWith('/api')) {\n return false;\n }\n\n // _next 관련 파일들\n if (pathname.startsWith('/_next') || pathname === '/favicon.ico') {\n return true;\n }\n\n // 확장자가 있으면 정적 자원\n return /\\.[a-zA-Z0-9]+$/.test(pathname);\n};\n"]}
|