diff --git a/middlewares/bookingFlow.ts b/middlewares/bookingFlow.ts index 74c3818f1..098ca9108 100644 --- a/middlewares/bookingFlow.ts +++ b/middlewares/bookingFlow.ts @@ -2,10 +2,6 @@ import { NextResponse } from "next/server" import { bookingFlow } from "@/constants/routes/hotelReservation" -import { resolve as resolveEntry } from "@/utils/entry" -import { findLang } from "@/utils/languages" -import { removeTrailingSlash } from "@/utils/url" - import { getDefaultRequestHeaders } from "./utils" import type { NextMiddleware } from "next/server" @@ -13,8 +9,6 @@ import type { NextMiddleware } from "next/server" import type { MiddlewareMatcher } from "@/types/middleware" export const middleware: NextMiddleware = async (request) => { - const { nextUrl } = request - const headers = getDefaultRequestHeaders(request) return NextResponse.next({ request: { diff --git a/middlewares/cmsContent.ts b/middlewares/cmsContent.ts index 8facd7607..3d931ebbe 100644 --- a/middlewares/cmsContent.ts +++ b/middlewares/cmsContent.ts @@ -6,7 +6,7 @@ import { resolve as resolveEntry } from "@/utils/entry" import { findLang } from "@/utils/languages" import { removeTrailingSlash } from "@/utils/url" -import { getDefaultRequestHeaders } from "./utils" +import { fetchAndCacheEntry, getDefaultRequestHeaders } from "./utils" import type { NextMiddleware } from "next/server" @@ -21,7 +21,10 @@ export const middleware: NextMiddleware = async (request) => { const pathNameWithoutLang = pathWithoutTrailingSlash.replace(`/${lang}`, "") const searchParams = new URLSearchParams(request.nextUrl.searchParams) - const { contentType, uid } = await resolveEntry(pathNameWithoutLang, lang) + const { contentType, uid } = await fetchAndCacheEntry( + pathNameWithoutLang, + lang + ) if (!contentType || !uid) { throw notFound( diff --git a/middlewares/myPages.ts b/middlewares/myPages.ts index fcadc8736..28c375f13 100644 --- a/middlewares/myPages.ts +++ b/middlewares/myPages.ts @@ -9,10 +9,9 @@ import { import { env } from "@/env/server" import { internalServerError, notFound } from "@/server/errors/next" -import { resolve as resolveEntry } from "@/utils/entry" import { findLang } from "@/utils/languages" -import { getDefaultRequestHeaders } from "./utils" +import { fetchAndCacheEntry, getDefaultRequestHeaders } from "./utils" import type { NextMiddleware } from "next/server" @@ -40,8 +39,11 @@ export const middleware: NextMiddleware = async (request) => { } const pathNameWithoutLang = nextUrl.pathname.replace(`/${lang}`, "") - const { uid, contentType } = await resolveEntry(pathNameWithoutLang, lang) - if (!uid) { + const { uid, contentType } = await fetchAndCacheEntry( + pathNameWithoutLang, + lang + ) + if (!uid || !contentType) { throw notFound( `Unable to resolve CMS entry for locale "${lang}": ${pathNameWithoutLang}` ) diff --git a/middlewares/utils.ts b/middlewares/utils.ts index 0cf1c5b46..91e06a68d 100644 --- a/middlewares/utils.ts +++ b/middlewares/utils.ts @@ -1,5 +1,9 @@ +import { stringify } from "querystring" + +import { Lang } from "@/constants/languages" import { env } from "@/env/server" +import { resolve as resolveEntry } from "@/utils/entry" import { findLang } from "@/utils/languages" import { removeTrailingSlash } from "@/utils/url" @@ -31,3 +35,49 @@ export function getDefaultRequestHeaders(request: NextRequest) { return headers } + +const entryResponseCache: Map< + string, + { + contentType: string | null + uid: string | null + expiresAt: number + } +> = new Map() +let size: number = 0 + +export const fetchAndCacheEntry = async (path: string, lang: Lang) => { + const cacheKey = `${path + lang}` + const cachedResponse = entryResponseCache.get(cacheKey) + + if (cachedResponse && cachedResponse.expiresAt > Date.now() / 1000) { + console.log("[CMS MIDDLEWARE]: CACHE HIT") + return cachedResponse + } + + if (cachedResponse && cachedResponse.expiresAt < Date.now() / 1000) { + console.log("[CMS MIDDLEWARE]: CACHE STALE") + size -= JSON.stringify(cachedResponse).length + entryResponseCache.delete(cacheKey) + } else { + console.log("[CMS MIDDLEWARE]: CACHE MISS") + } + + const { contentType, uid } = await resolveEntry(path, lang) + let expiresAt = Date.now() / 1000 + if (!contentType || !uid) { + expiresAt += 600 + } else { + expiresAt += 3600 * 12 + } + const entryCache = { contentType, uid, expiresAt } + size += JSON.stringify(entryCache).length + console.log("[CMS MIDDLEWARE] Adding to cache", entryCache) + console.log("[CMS MIDDLEWARE] Cache size (total)", size) + entryResponseCache.set(cacheKey, entryCache) + + return { + contentType, + uid, + } +} diff --git a/middlewares/webView.ts b/middlewares/webView.ts index d29001796..e06cefb0b 100644 --- a/middlewares/webView.ts +++ b/middlewares/webView.ts @@ -13,13 +13,13 @@ import { decryptData } from "@/utils/aes" import { resolve as resolveEntry } from "@/utils/entry" import { findLang } from "@/utils/languages" -import { getDefaultRequestHeaders } from "./utils" +import { fetchAndCacheEntry, getDefaultRequestHeaders } from "./utils" import type { MiddlewareMatcher } from "@/types/middleware" export const middleware: NextMiddleware = async (request) => { const { nextUrl } = request - const lang = findLang(nextUrl.pathname) + const lang = findLang(nextUrl.pathname)! const loginTypeHeader = request.headers.get("loginType") const loginTypeSearchParam = nextUrl.searchParams.get("loginType") @@ -64,7 +64,7 @@ export const middleware: NextMiddleware = async (request) => { const pathNameWithoutLang = nextUrl.pathname.replace(`/${lang}/webview`, "") - const { uid } = await resolveEntry(pathNameWithoutLang, lang) + const { uid } = await fetchAndCacheEntry(pathNameWithoutLang, lang) if (!uid) { throw notFound( `Unable to resolve CMS entry for locale "${lang}": ${pathNameWithoutLang}`