diff --git a/packages/react-contexts/package.json b/packages/react-contexts/package.json index a33e5306e0..712f686d3e 100644 --- a/packages/react-contexts/package.json +++ b/packages/react-contexts/package.json @@ -72,7 +72,8 @@ "semver": "^7.5.4", "set-cookie-parser": "^2.7.1", "ua-parser-js": "^1.0.37", - "universal-cookie": "^4.0.4" + "universal-cookie": "^4.0.4", + "uuid": "^11.1.0" }, "devDependencies": { "@types/qs": "^6.9.9", diff --git a/packages/react-contexts/src/middlewares/chain.ts b/packages/react-contexts/src/middlewares/chain.ts index 80c03ff054..9f89425d92 100644 --- a/packages/react-contexts/src/middlewares/chain.ts +++ b/packages/react-contexts/src/middlewares/chain.ts @@ -1,16 +1,11 @@ -import { NextResponse } from 'next/server' -import type { NextFetchEvent, NextRequest } from 'next/server' +import { NextMiddleware, NextResponse } from 'next/server' -import { CustomMiddleware, MiddlewareFactory } from './types' +import { MiddlewareFactory } from './types' -/** - * TF 14.0.11의 middlewares/src/chain 참고하여 작성 - * https://github.com/titicacadev/triple-frontend/blob/ceee9a7116dfbf39cc1363013a43cfb0060a9539/packages/middlewares/src/chain.ts - */ export function chain( functions: MiddlewareFactory[], index = 0, -): CustomMiddleware { +): NextMiddleware { const current = functions[index] if (current) { @@ -18,11 +13,7 @@ export function chain( return current(next) } - return ( - request: NextRequest, - event: NextFetchEvent, - response: NextResponse, - ) => { - return response + return () => { + return NextResponse.next() } } diff --git a/packages/react-contexts/src/middlewares/constants.ts b/packages/react-contexts/src/middlewares/constants.ts index 1203e84c5a..70305190b9 100644 --- a/packages/react-contexts/src/middlewares/constants.ts +++ b/packages/react-contexts/src/middlewares/constants.ts @@ -1,2 +1,3 @@ export const TP_TK = 'TP_TK' export const TP_SE = 'TP_SE' +export const X_TRIPLE_WEB_DEVICE_ID = 'x-triple-web-device-id' diff --git a/packages/react-contexts/src/middlewares/index.ts b/packages/react-contexts/src/middlewares/index.ts index bb364a75e9..6ccb4d38a5 100644 --- a/packages/react-contexts/src/middlewares/index.ts +++ b/packages/react-contexts/src/middlewares/index.ts @@ -1,10 +1,11 @@ import { chain } from './chain' import type { MiddlewareFactory } from './types' import { refreshSessionMiddleware } from './refresh-session' +import { setWebDeviceIdMiddleware } from './set-web-device-id' export { oldTripleIosCookiesMiddleware } from './old-triple-ios-cookie' export const constructMiddleware = (functions: MiddlewareFactory[]) => - chain([...functions, refreshSessionMiddleware]) + chain([...functions, refreshSessionMiddleware, setWebDeviceIdMiddleware]) export * from './types' diff --git a/packages/react-contexts/src/middlewares/old-triple-ios-cookie.ts b/packages/react-contexts/src/middlewares/old-triple-ios-cookie.ts index ce7c7bbf92..4af362e0af 100644 --- a/packages/react-contexts/src/middlewares/old-triple-ios-cookie.ts +++ b/packages/react-contexts/src/middlewares/old-triple-ios-cookie.ts @@ -1,19 +1,23 @@ -import { NextRequest, NextResponse, NextFetchEvent } from 'next/server' +import { + NextRequest, + NextResponse, + NextFetchEvent, + NextMiddleware, +} from 'next/server' import satisfies from 'semver/functions/satisfies' import { parseApp } from '../user-agent-context' -import { CustomMiddleware } from './types' - /** * TF 13.42.1의 react-contexts/src/middleware 참고하여 작성 * https://github.com/titicacadev/triple-frontend/blob/8d002e80f9ff187d6a06b6a2695c48f1d5383662/packages/react-contexts/src/middleware.ts */ -export function oldTripleIosCookiesMiddleware( - customMiddleware: CustomMiddleware, -) { - return function middleware(request: NextRequest, event: NextFetchEvent) { - const response = NextResponse.next() +export function oldTripleIosCookiesMiddleware(next: NextMiddleware) { + return async function middleware( + request: NextRequest, + event: NextFetchEvent, + ) { + const response = (await next(request, event)) as NextResponse const userAgent = request.headers.get('User-Agent') @@ -22,7 +26,7 @@ export function oldTripleIosCookiesMiddleware( const tripleApp = userAgent ? parseApp(userAgent) : null if (!userAgent || (host && !!tripleApp)) { - return customMiddleware(request, event, response) + return response } try { @@ -45,6 +49,6 @@ export function oldTripleIosCookiesMiddleware( // semver 파싱 에러가 발생하면 ignore 합니다. } - return customMiddleware(request, event, response) + return response } } diff --git a/packages/react-contexts/src/middlewares/refresh-session.ts b/packages/react-contexts/src/middlewares/refresh-session.ts index 6edc005750..386c86768c 100644 --- a/packages/react-contexts/src/middlewares/refresh-session.ts +++ b/packages/react-contexts/src/middlewares/refresh-session.ts @@ -1,20 +1,25 @@ -import { NextFetchEvent, NextRequest, NextResponse } from 'next/server' +import { + NextFetchEvent, + NextMiddleware, + NextRequest, + NextResponse, +} from 'next/server' import { get, post } from '@titicaca/fetcher' import { parseString, splitCookiesString } from 'set-cookie-parser' -import { CustomMiddleware } from './types' import { TP_SE, TP_TK } from './constants' -export function refreshSessionMiddleware(customMiddleware: CustomMiddleware) { +export function refreshSessionMiddleware(next: NextMiddleware) { return async function middleware( request: NextRequest, event: NextFetchEvent, ) { + const response = (await next(request, event)) as NextResponse const url = request.nextUrl const isPageUrl = url.pathname.match('^/((?!(api|static|.*\\..*|_next)).*)') if (!isPageUrl) { - return customMiddleware(request, event, NextResponse.next()) + return response } const allCookies = request.cookies.getAll() @@ -25,7 +30,7 @@ export function refreshSessionMiddleware(customMiddleware: CustomMiddleware) { const cookies = deriveAllCookies(request.cookies.getAll()) if (!isSessionExisted) { - return customMiddleware(request, event, NextResponse.next()) + return response } const options = { @@ -36,7 +41,7 @@ export function refreshSessionMiddleware(customMiddleware: CustomMiddleware) { const firstTrialResponse = await get('/api/users/me', options) if (firstTrialResponse.status !== 401) { - return customMiddleware(request, event, NextResponse.next()) + return response } /** @@ -73,10 +78,10 @@ export function refreshSessionMiddleware(customMiddleware: CustomMiddleware) { response.headers.set('set-cookie', setCookie) - return customMiddleware(request, event, response) + return response } } - return customMiddleware(request, event, NextResponse.next()) + return response } } diff --git a/packages/react-contexts/src/middlewares/set-web-device-id.ts b/packages/react-contexts/src/middlewares/set-web-device-id.ts new file mode 100644 index 0000000000..998f8f5f53 --- /dev/null +++ b/packages/react-contexts/src/middlewares/set-web-device-id.ts @@ -0,0 +1,38 @@ +import { + NextFetchEvent, + NextMiddleware, + NextRequest, + NextResponse, +} from 'next/server' +import { v4 as uuidV4 } from 'uuid' + +import { getTripleApp } from './utils/get-triple-app' +import { X_TRIPLE_WEB_DEVICE_ID } from './constants' + +export function setWebDeviceIdMiddleware(next: NextMiddleware) { + return async function middleware( + request: NextRequest, + event: NextFetchEvent, + ) { + const response = (await next(request, event)) as NextResponse + const tripleApp = getTripleApp(request) + + if (tripleApp) { + return response + } + + const allCookies = request.cookies.getAll() + const hasWebDeviceId = allCookies.some( + ({ name }) => name === X_TRIPLE_WEB_DEVICE_ID, + ) + + if (!hasWebDeviceId && response?.cookies) { + const randomWebDeviceId = uuidV4() + response.cookies.set(X_TRIPLE_WEB_DEVICE_ID, randomWebDeviceId, { + secure: true, + }) + } + + return response + } +} diff --git a/packages/react-contexts/src/middlewares/types.ts b/packages/react-contexts/src/middlewares/types.ts index 6638b6b286..1e3a7a7e85 100644 --- a/packages/react-contexts/src/middlewares/types.ts +++ b/packages/react-contexts/src/middlewares/types.ts @@ -1,12 +1,3 @@ -import { NextMiddlewareResult } from 'next/dist/server/web/types' -import { NextFetchEvent, NextRequest, NextResponse } from 'next/server' +import { NextMiddleware } from 'next/server' -export type CustomMiddleware = ( - request: NextRequest, - event: NextFetchEvent, - response: NextResponse, -) => NextMiddlewareResult | Promise - -export type MiddlewareFactory = ( - middleware: CustomMiddleware, -) => CustomMiddleware +export type MiddlewareFactory = (middleware: NextMiddleware) => NextMiddleware diff --git a/packages/react-contexts/src/middlewares/utils/get-triple-app.ts b/packages/react-contexts/src/middlewares/utils/get-triple-app.ts new file mode 100644 index 0000000000..19e69efaab --- /dev/null +++ b/packages/react-contexts/src/middlewares/utils/get-triple-app.ts @@ -0,0 +1,10 @@ +import { NextRequest } from 'next/server' + +import { parseApp } from '../../user-agent-context' + +export function getTripleApp(request: NextRequest) { + const userAgent = request.headers.get('User-Agent') + const tripleApp = userAgent ? parseApp(userAgent) : null + + return tripleApp +} diff --git a/packages/react-contexts/src/user-agent-context/utils.ts b/packages/react-contexts/src/user-agent-context/utils.ts index 6c414667ee..e435ab14a4 100644 --- a/packages/react-contexts/src/user-agent-context/utils.ts +++ b/packages/react-contexts/src/user-agent-context/utils.ts @@ -5,7 +5,7 @@ enum AppName { Android = 'Triple-Android', } -interface App { +export interface App { name: AppName version: string } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 69a1534440..d2d7434606 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1185,6 +1185,9 @@ importers: universal-cookie: specifier: ^4.0.4 version: 4.0.4 + uuid: + specifier: ^11.1.0 + version: 11.1.0 devDependencies: '@types/qs': specifier: ^6.9.9 @@ -11591,6 +11594,10 @@ packages: resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} engines: {node: '>= 0.4.0'} + uuid@11.1.0: + resolution: {integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==} + hasBin: true + uuid@9.0.0: resolution: {integrity: sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==} hasBin: true @@ -24465,6 +24472,8 @@ snapshots: utils-merge@1.0.1: {} + uuid@11.1.0: {} + uuid@9.0.0: {} uvu@0.5.6: