diff --git a/.env b/.env deleted file mode 100644 index d116a87a8..000000000 --- a/.env +++ /dev/null @@ -1,4 +0,0 @@ -# See update-dotenv.mjs -AUTH_URL="REPLACE-ON-NETLIFY-BUILD" -NEXTAUTH_URL="REPLACE-ON-NETLIFY-BUILD" -PUBLIC_URL="REPLACED-ON-NETLIFY-BUILD" diff --git a/app/[lang]/(live)/(protected)/logout/route.ts b/app/[lang]/(live)/(protected)/logout/route.ts index 2bb2f0a52..db32e1c48 100644 --- a/app/[lang]/(live)/(protected)/logout/route.ts +++ b/app/[lang]/(live)/(protected)/logout/route.ts @@ -4,6 +4,7 @@ import { AuthError } from "next-auth" import { Lang } from "@/constants/languages" import { env } from "@/env/server" import { internalServerError } from "@/server/errors/next" +import { getPublicURL } from "@/server/utils" import { signOut } from "@/auth" @@ -11,6 +12,8 @@ export async function GET( request: NextRequest, context: { params: { lang: Lang } } ) { + const publicURL = getPublicURL(request) + let redirectTo: string = "" const returnUrl = request.headers.get("x-returnurl") @@ -39,7 +42,7 @@ export async function GET( // Make relative URL to absolute URL if (redirectTo.startsWith("/")) { console.log(`[logout] make redirectTo absolute, from ${redirectTo}`) - redirectTo = new URL(redirectTo, env.PUBLIC_URL).href + redirectTo = new URL(redirectTo, publicURL).href console.log(`[logout] make redirectTo absolute, to ${redirectTo}`) } diff --git a/app/[lang]/(live)/(public)/login/route.ts b/app/[lang]/(live)/(public)/login/route.ts index b038205e6..2d91c0d5f 100644 --- a/app/[lang]/(live)/(public)/login/route.ts +++ b/app/[lang]/(live)/(public)/login/route.ts @@ -4,6 +4,7 @@ import { AuthError } from "next-auth" import { Lang } from "@/constants/languages" import { env } from "@/env/server" import { internalServerError } from "@/server/errors/next" +import { getPublicURL } from "@/server/utils" import { signIn } from "@/auth" @@ -11,9 +12,7 @@ export async function GET( request: NextRequest, context: { params: { lang: Lang } } ) { - if (!env.PUBLIC_URL) { - throw internalServerError("No value for env.PUBLIC_URL") - } + const publicURL = getPublicURL(request) let redirectHeaders: Headers | undefined = undefined let redirectTo: string @@ -54,7 +53,7 @@ export async function GET( // Make relative URL to absolute URL if (redirectTo.startsWith("/")) { console.log(`[login] make redirectTo absolute, from ${redirectTo}`) - redirectTo = new URL(redirectTo, env.PUBLIC_URL).href + redirectTo = new URL(redirectTo, publicURL).href console.log(`[login] make redirectTo absolute, to ${redirectTo}`) } @@ -131,7 +130,7 @@ export async function GET( * because user might choose to do Email link login. * */ // The `for_origin` param is used to make Curity email login functionality working. - for_origin: env.PUBLIC_URL, + for_origin: publicURL, // This is new param set for differentiate between the Magic link login of New web and current web version: "2", } diff --git a/app/[lang]/(live)/(public)/verifymagiclink/route.ts b/app/[lang]/(live)/(public)/verifymagiclink/route.ts index 12c4b132f..81fa277c3 100644 --- a/app/[lang]/(live)/(public)/verifymagiclink/route.ts +++ b/app/[lang]/(live)/(public)/verifymagiclink/route.ts @@ -5,6 +5,7 @@ import { Lang } from "@/constants/languages" import { login } from "@/constants/routes/handleAuth" import { env } from "@/env/server" import { badRequest, internalServerError } from "@/server/errors/next" +import { getPublicURL } from "@/server/utils" import { signIn } from "@/auth" @@ -12,9 +13,7 @@ export async function GET( request: NextRequest, context: { params: { lang: Lang } } ) { - if (!env.PUBLIC_URL) { - throw internalServerError("No value for env.PUBLIC_URL") - } + const publicURL = getPublicURL(request) const loginKey = request.nextUrl.searchParams.get("loginKey") if (!loginKey) { @@ -44,7 +43,7 @@ export async function GET( console.log( `[verifymagiclink] make redirectTo absolute, from ${redirectTo}` ) - redirectTo = new URL(redirectTo, env.PUBLIC_URL).href + redirectTo = new URL(redirectTo, publicURL).href console.log(`[verifymagiclink] make redirectTo absolute, to ${redirectTo}`) } @@ -69,7 +68,7 @@ export async function GET( ui_locales: context.params.lang, scope: ["openid", "profile"].join(" "), loginKey: loginKey, - for_origin: env.PUBLIC_URL, + for_origin: publicURL, acr_values: "abc", version: "2", } diff --git a/app/api/web/add-card-callback/[lang]/route.ts b/app/api/web/add-card-callback/[lang]/route.ts index 63eb19942..e664124ed 100644 --- a/app/api/web/add-card-callback/[lang]/route.ts +++ b/app/api/web/add-card-callback/[lang]/route.ts @@ -4,14 +4,17 @@ import { env } from "process" import { Lang } from "@/constants/languages" import { profile } from "@/constants/routes/myPages" import { serverClient } from "@/lib/trpc/server" +import { getPublicURL } from "@/server/utils" export async function GET( request: NextRequest, { params }: { params: { lang: string } } ) { + const publicURL = getPublicURL(request) + console.log(`[add-card] callback started`) const lang = params.lang as Lang - const returnUrl = new URL(`${env.PUBLIC_URL}/${profile[lang ?? Lang.en]}`) + const returnUrl = new URL(`${publicURL}/${profile[lang ?? Lang.en]}`) try { const searchParams = request.nextUrl.searchParams diff --git a/app/api/web/envtest-dynamic-edge/route.ts b/app/api/web/envtest-dynamic-edge/route.ts deleted file mode 100644 index d2a12f7bf..000000000 --- a/app/api/web/envtest-dynamic-edge/route.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { NextResponse } from "next/server" - -import { env } from "@/env/server" - -import type { NextRequest } from "next/server" - -export async function GET(request: NextRequest) { - const e = process.env - console.log({ process_env: process.env }) - - const urlVar = "PUBLIC_URL" - const nextAuthUrlVar = "NEXTAUTH_URL" - const nextAuthUrlVar2 = "AUTH_URL" - const envTestVar = "ENVTEST" - - const values = { - env_url: env.PUBLIC_URL, - static_url: process.env.PUBLIC_URL, - dynamic_url: e[urlVar], - env_envtest: env.ENVTEST, - static_envtest: process.env.ENVTEST, - dynamic_envtest: e[envTestVar], - env_nextauth: env.NEXTAUTH_URL, - static_nextauth: process.env.NEXTAUTH_URL, - dynamic_nextauth: e[nextAuthUrlVar], - env_nextauth2: env.AUTH_URL, - static_nextauth2: process.env.AUTH_URL, - dynamic_nextauth2: e[nextAuthUrlVar2], - } - - console.log(values) - - return NextResponse.json(values) -} - -export const dynamic = "force-dynamic" - -export const runtime = "edge" diff --git a/app/api/web/envtest-dynamic-load-file/route.ts b/app/api/web/envtest-dynamic-load-file/route.ts deleted file mode 100644 index 115f12f77..000000000 --- a/app/api/web/envtest-dynamic-load-file/route.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { config } from "dotenv" -import { NextResponse } from "next/server" - -import { env } from "@/env/server" - -import type { NextRequest } from "next/server" - -config({ path: "./.env" }) - -export async function GET(request: NextRequest) { - const e = process.env - console.log({ process_env: process.env }) - - const urlVar = "PUBLIC_URL" - const nextAuthUrlVar = "NEXTAUTH_URL" - const nextAuthUrlVar2 = "AUTH_URL" - const envTestVar = "ENVTEST" - - const values = { - env_url: env.PUBLIC_URL, - static_url: process.env.PUBLIC_URL, - dynamic_url: e[urlVar], - env_envtest: env.ENVTEST, - static_envtest: process.env.ENVTEST, - dynamic_envtest: e[envTestVar], - env_nextauth: env.NEXTAUTH_URL, - static_nextauth: process.env.NEXTAUTH_URL, - dynamic_nextauth: e[nextAuthUrlVar], - env_nextauth2: env.AUTH_URL, - static_nextauth2: process.env.AUTH_URL, - dynamic_nextauth2: e[nextAuthUrlVar2], - } - - console.log(values) - - return NextResponse.json(values) -} - -export const dynamic = "force-dynamic" diff --git a/app/api/web/envtest-dynamic-load/route.ts b/app/api/web/envtest-dynamic-load/route.ts deleted file mode 100644 index 18c964526..000000000 --- a/app/api/web/envtest-dynamic-load/route.ts +++ /dev/null @@ -1,38 +0,0 @@ -import "dotenv/config" - -import { NextResponse } from "next/server" - -import { env } from "@/env/server" - -import type { NextRequest } from "next/server" - -export async function GET(request: NextRequest) { - const e = process.env - console.log({ process_env: process.env }) - - const urlVar = "PUBLC_URL" - const nextAuthUrlVar = "NEXTAUTH_URL" - const nextAuthUrlVar2 = "AUTH_URL" - const envTestVar = "ENVTEST" - - const values = { - env_url: env.PUBLIC_URL, - static_url: process.env.PUBLIC_URL, - dynamic_url: e[urlVar], - env_envtest: env.ENVTEST, - static_envtest: process.env.ENVTEST, - dynamic_envtest: e[envTestVar], - env_nextauth: env.NEXTAUTH_URL, - static_nextauth: process.env.NEXTAUTH_URL, - dynamic_nextauth: e[nextAuthUrlVar], - env_nextauth2: env.AUTH_URL, - static_nextauth2: process.env.AUTH_URL, - dynamic_nextauth2: e[nextAuthUrlVar2], - } - - console.log(values) - - return NextResponse.json(values) -} - -export const dynamic = "force-dynamic" diff --git a/app/api/web/envtest-dynamic-override/route.ts b/app/api/web/envtest-dynamic-override/route.ts deleted file mode 100644 index 4d45b8e5f..000000000 --- a/app/api/web/envtest-dynamic-override/route.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { config } from "dotenv" -import { NextResponse } from "next/server" - -import { env } from "@/env/server" - -import type { NextRequest } from "next/server" - -config({ debug: true, override: true }) - -export async function GET(request: NextRequest) { - const e = process.env - console.log({ process_env: process.env }) - - const urlVar = "PUBLC_URL" - const nextAuthUrlVar = "NEXTAUTH_URL" - const nextAuthUrlVar2 = "AUTH_URL" - const envTestVar = "ENVTEST" - - const values = { - env_url: env.PUBLIC_URL, - static_url: process.env.PUBLIC_URL, - dynamic_url: e[urlVar], - env_envtest: env.ENVTEST, - static_envtest: process.env.ENVTEST, - dynamic_envtest: e[envTestVar], - env_nextauth: env.NEXTAUTH_URL, - static_nextauth: process.env.NEXTAUTH_URL, - dynamic_nextauth: e[nextAuthUrlVar], - env_nextauth2: env.AUTH_URL, - static_nextauth2: process.env.AUTH_URL, - dynamic_nextauth2: e[nextAuthUrlVar2], - } - - console.log(values) - - return NextResponse.json(values) -} - -export const dynamic = "force-dynamic" diff --git a/app/api/web/envtest-dynamic/route.ts b/app/api/web/envtest-dynamic/route.ts deleted file mode 100644 index 386817938..000000000 --- a/app/api/web/envtest-dynamic/route.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { NextResponse } from "next/server" - -import { env } from "@/env/server" - -import type { NextRequest } from "next/server" - -export async function GET(request: NextRequest) { - const e = process.env - console.log({ process_env: process.env }) - - const urlVar = "PUBLIC_URL" - const nextAuthUrlVar = "NEXTAUTH_URL" - const nextAuthUrlVar2 = "AUTH_URL" - const envTestVar = "ENVTEST" - - const values = { - env_url: env.PUBLIC_URL, - static_url: process.env.PUBLIC_URL, - dynamic_url: e[urlVar], - env_envtest: env.ENVTEST, - static_envtest: process.env.ENVTEST, - dynamic_envtest: e[envTestVar], - env_nextauth: env.NEXTAUTH_URL, - static_nextauth: process.env.NEXTAUTH_URL, - dynamic_nextauth: e[nextAuthUrlVar], - env_nextauth2: env.AUTH_URL, - static_nextauth2: process.env.AUTH_URL, - dynamic_nextauth2: e[nextAuthUrlVar2], - } - - console.log(values) - - return NextResponse.json(values) -} - -export const dynamic = "force-dynamic" diff --git a/app/api/web/envtest-static-load-file/route.ts b/app/api/web/envtest-static-load-file/route.ts deleted file mode 100644 index f1a83978a..000000000 --- a/app/api/web/envtest-static-load-file/route.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { config } from "dotenv" -import { NextResponse } from "next/server" - -import { env } from "@/env/server" - -import type { NextRequest } from "next/server" - -config({ path: "./.env" }) - -export async function GET(request: NextRequest) { - const e = process.env - console.log({ process_env: process.env }) - - const urlVar = "PUBLIC_URL" - const nextAuthUrlVar = "NEXTAUTH_URL" - const nextAuthUrlVar2 = "AUTH_URL" - const envTestVar = "ENVTEST" - - const values = { - env_url: env.PUBLIC_URL, - static_url: process.env.PUBLIC_URL, - dynamic_url: e[urlVar], - env_envtest: env.ENVTEST, - static_envtest: process.env.ENVTEST, - dynamic_envtest: e[envTestVar], - env_nextauth: env.NEXTAUTH_URL, - static_nextauth: process.env.NEXTAUTH_URL, - dynamic_nextauth: e[nextAuthUrlVar], - env_nextauth2: env.AUTH_URL, - static_nextauth2: process.env.AUTH_URL, - dynamic_nextauth2: e[nextAuthUrlVar2], - } - - console.log(values) - - return NextResponse.json(values) -} diff --git a/app/api/web/envtest-static-load/route.ts b/app/api/web/envtest-static-load/route.ts deleted file mode 100644 index 4e360a891..000000000 --- a/app/api/web/envtest-static-load/route.ts +++ /dev/null @@ -1,36 +0,0 @@ -import "dotenv/config" - -import { NextResponse } from "next/server" - -import { env } from "@/env/server" - -import type { NextRequest } from "next/server" - -export async function GET(request: NextRequest) { - const e = process.env - console.log({ process_env: process.env }) - - const urlVar = "PUBLIC_URL" - const nextAuthUrlVar = "NEXTAUTH_URL" - const nextAuthUrlVar2 = "AUTH_URL" - const envTestVar = "ENVTEST" - - const values = { - env_url: env.PUBLIC_URL, - static_url: process.env.PUBLIC_URL, - dynamic_url: e[urlVar], - env_envtest: env.ENVTEST, - static_envtest: process.env.ENVTEST, - dynamic_envtest: e[envTestVar], - env_nextauth: env.NEXTAUTH_URL, - static_nextauth: process.env.NEXTAUTH_URL, - dynamic_nextauth: e[nextAuthUrlVar], - env_nextauth2: env.AUTH_URL, - static_nextauth2: process.env.AUTH_URL, - dynamic_nextauth2: e[nextAuthUrlVar2], - } - - console.log(values) - - return NextResponse.json(values) -} diff --git a/app/api/web/envtest-static-override/route.ts b/app/api/web/envtest-static-override/route.ts deleted file mode 100644 index d844016c5..000000000 --- a/app/api/web/envtest-static-override/route.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { config } from "dotenv" -import { NextResponse } from "next/server" - -import { env } from "@/env/server" - -import type { NextRequest } from "next/server" - -config({ debug: true, override: true }) - -export async function GET(request: NextRequest) { - const e = process.env - console.log({ process_env: process.env }) - - const urlVar = "PUBLIC_URL" - const nextAuthUrlVar = "NEXTAUTH_URL" - const nextAuthUrlVar2 = "AUTH_URL" - const envTestVar = "ENVTEST" - - const values = { - env_url: env.PUBLIC_URL, - static_url: process.env.PUBLIC_URL, - dynamic_url: e[urlVar], - env_envtest: env.ENVTEST, - static_envtest: process.env.ENVTEST, - dynamic_envtest: e[envTestVar], - env_nextauth: env.NEXTAUTH_URL, - static_nextauth: process.env.NEXTAUTH_URL, - dynamic_nextauth: e[nextAuthUrlVar], - env_nextauth2: env.AUTH_URL, - static_nextauth2: process.env.AUTH_URL, - dynamic_nextauth2: e[nextAuthUrlVar2], - } - - console.log(values) - - return NextResponse.json(values) -} diff --git a/app/api/web/envtest-static/route.ts b/app/api/web/envtest-static/route.ts deleted file mode 100644 index 1c71b77ca..000000000 --- a/app/api/web/envtest-static/route.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { NextResponse } from "next/server" - -import { env } from "@/env/server" - -import type { NextRequest } from "next/server" - -export async function GET(request: NextRequest) { - const e = process.env - console.log({ process_env: process.env }) - - const urlVar = "PUBLIC_URL" - const nextAuthUrlVar = "NEXTAUTH_URL" - const nextAuthUrlVar2 = "AUTH_URL" - const envTestVar = "ENVTEST" - - const values = { - env_url: env.PUBLIC_URL, - static_url: process.env.PUBLIC_URL, - dynamic_url: e[urlVar], - env_envtest: env.ENVTEST, - static_envtest: process.env.ENVTEST, - dynamic_envtest: e[envTestVar], - env_nextauth: env.NEXTAUTH_URL, - static_nextauth: process.env.NEXTAUTH_URL, - dynamic_nextauth: e[nextAuthUrlVar], - env_nextauth2: env.AUTH_URL, - static_nextauth2: process.env.AUTH_URL, - dynamic_nextauth2: e[nextAuthUrlVar2], - } - - console.log(values) - - return NextResponse.json(values) -} diff --git a/app/api/web/payment-callback/[lang]/[status]/route.ts b/app/api/web/payment-callback/[lang]/[status]/route.ts index 0b8133c43..4154aff14 100644 --- a/app/api/web/payment-callback/[lang]/[status]/route.ts +++ b/app/api/web/payment-callback/[lang]/[status]/route.ts @@ -6,20 +6,21 @@ import { bookingConfirmation, payment, } from "@/constants/routes/hotelReservation" +import { getPublicURL } from "@/server/utils" export async function GET( request: NextRequest, { params }: { params: { lang: string; status: string } } ): Promise { + const publicURL = getPublicURL(request) + console.log(`[payment-callback] callback started`) const lang = params.lang as Lang const status = params.status - const returnUrl = new URL(`${env.PUBLIC_URL}/${payment[lang]}`) + const returnUrl = new URL(`${publicURL}/${payment[lang]}`) if (status === "success") { - const confirmationUrl = new URL( - `${env.PUBLIC_URL}/${bookingConfirmation[lang]}` - ) + const confirmationUrl = new URL(`${publicURL}/${bookingConfirmation[lang]}`) console.log(`[payment-callback] redirecting to: ${confirmationUrl}`) return NextResponse.redirect(confirmationUrl) } diff --git a/auth.ts b/auth.ts index 0de343626..3adc360f8 100644 --- a/auth.ts +++ b/auth.ts @@ -109,6 +109,7 @@ const curityProvider = { } satisfies OIDCConfig export const config = { + basePath: "/api/web/auth", debug: env.NEXTAUTH_DEBUG, providers: [curityProvider], redirectProxyUrl: env.NEXTAUTH_REDIRECT_PROXY_URL, @@ -233,4 +234,4 @@ export const { auth, signIn, signOut, -} = NextAuth(config) \ No newline at end of file +} = NextAuth(config) diff --git a/env/server.ts b/env/server.ts index b32150a1d..c4b9355b7 100644 --- a/env/server.ts +++ b/env/server.ts @@ -37,15 +37,15 @@ export const env = createEnv({ .default("false"), NEXTAUTH_REDIRECT_PROXY_URL: z.string().optional(), NEXTAUTH_SECRET: z.string(), - NEXTAUTH_URL: z.string().optional(), - AUTH_URL: z.string().optional(), + NEXTAUTH_URL: z.string().default(""), + AUTH_URL: z.string().default(""), NODE_ENV: z.enum(["development", "test", "production"]), PRINT_QUERY: z .string() .refine((s) => s === "true" || s === "false") .transform((s) => s === "true") .default("false"), - PUBLIC_URL: z.string().optional(), + PUBLIC_URL: z.string().default(""), REVALIDATE_SECRET: z.string(), SALESFORCE_PREFERENCE_BASE_URL: z.string(), SEAMLESS_LOGIN_DA: z.string(), diff --git a/middlewares/authRequired.ts b/middlewares/authRequired.ts index 0e50330ee..09781ac56 100644 --- a/middlewares/authRequired.ts +++ b/middlewares/authRequired.ts @@ -2,8 +2,7 @@ import { NextResponse } from "next/server" import { authRequired, mfaRequired } from "@/constants/routes/authRequired" import { login } from "@/constants/routes/handleAuth" -import { env } from "@/env/server" -import { internalServerError } from "@/server/errors/next" +import { getPublicNextURL } from "@/server/utils" import { auth } from "@/auth" import { findLang } from "@/utils/languages" @@ -44,14 +43,7 @@ export const middleware = auth(async (request) => { const isLoggedIn = !!request.auth const hasError = request.auth?.error - if (!env.PUBLIC_URL) { - throw internalServerError("Missing value for env.PUBLIC_URL") - } - - const publicUrl = new URL(env.PUBLIC_URL) - const nextUrlPublic = nextUrl.clone() - nextUrlPublic.host = publicUrl.host - nextUrlPublic.hostname = publicUrl.hostname + const nextUrlPublic = getPublicNextURL(request) /** * Function to validate MFA from token data diff --git a/middlewares/currentWebLogout.ts b/middlewares/currentWebLogout.ts index c358012f2..2e52346a2 100644 --- a/middlewares/currentWebLogout.ts +++ b/middlewares/currentWebLogout.ts @@ -2,6 +2,7 @@ import { NextResponse } from "next/server" import { env } from "@/env/server" import { badRequest, internalServerError } from "@/server/errors/next" +import { getPublicURL } from "@/server/utils" import { findLang } from "@/utils/languages" @@ -16,10 +17,7 @@ export const middleware: NextMiddleware = (request) => { } const lang = findLang(request.nextUrl.pathname)! - if (!env.PUBLIC_URL) { - throw internalServerError("No value for env.PUBLIC_URL") - } - const redirectTo = env.PUBLIC_URL + const redirectTo = getPublicURL(request) const headers = new Headers(request.headers) headers.set("x-returnurl", redirectTo) diff --git a/middlewares/myPages.ts b/middlewares/myPages.ts index 28c375f13..6e27f10a9 100644 --- a/middlewares/myPages.ts +++ b/middlewares/myPages.ts @@ -8,6 +8,7 @@ import { } from "@/constants/routes/myPages" import { env } from "@/env/server" import { internalServerError, notFound } from "@/server/errors/next" +import { getPublicNextURL } from "@/server/utils" import { findLang } from "@/utils/languages" @@ -23,17 +24,9 @@ export const middleware: NextMiddleware = async (request) => { const myPagesRoot = myPages[lang] if (nextUrl.pathname === myPagesRoot) { - if (!env.PUBLIC_URL) { - throw internalServerError("Missing value for env.PUBLIC_URL") - } - - const publicUrl = new URL(env.PUBLIC_URL) - const nextUrlClone = nextUrl.clone() - nextUrlClone.host = publicUrl.host - nextUrlClone.hostname = publicUrl.hostname - + const nextUrlPublic = getPublicNextURL(request) const overviewUrl = overview[lang] - const redirectUrl = new URL(overviewUrl, nextUrlClone) + const redirectUrl = new URL(overviewUrl, nextUrlPublic) console.log(`[myPages] redirecting to: ${redirectUrl}`) return NextResponse.redirect(redirectUrl) } diff --git a/middlewares/utils.ts b/middlewares/utils.ts index 91e06a68d..18714d28f 100644 --- a/middlewares/utils.ts +++ b/middlewares/utils.ts @@ -1,7 +1,5 @@ -import { stringify } from "querystring" - import { Lang } from "@/constants/languages" -import { env } from "@/env/server" +import { getPublicNextURL } from "@/server/utils" import { resolve as resolveEntry } from "@/utils/entry" import { findLang } from "@/utils/languages" @@ -11,18 +9,7 @@ import type { NextRequest } from "next/server" export function getDefaultRequestHeaders(request: NextRequest) { const lang = findLang(request.nextUrl.pathname)! - - let nextUrl - if (env.PUBLIC_URL) { - const publicUrl = new URL(env.PUBLIC_URL) - const nextUrlPublic = request.nextUrl.clone() - nextUrlPublic.host = publicUrl.host - nextUrlPublic.hostname = publicUrl.hostname - nextUrl = nextUrlPublic - } else { - nextUrl = request.nextUrl - } - + const nextUrlPublic = getPublicNextURL(request) const headers = new Headers(request.headers) headers.set("x-lang", lang) headers.set( @@ -31,7 +18,7 @@ export function getDefaultRequestHeaders(request: NextRequest) { request.nextUrl.pathname.replace(`/${lang}`, "").replace(`/webview`, "") ) ) - headers.set("x-url", removeTrailingSlash(nextUrl.href)) + headers.set("x-url", removeTrailingSlash(nextUrlPublic.href)) return headers } diff --git a/netlify.toml b/netlify.toml index 022eee2ee..850405109 100644 --- a/netlify.toml +++ b/netlify.toml @@ -30,6 +30,3 @@ package = "@netlify/plugin-nextjs" [images] remote_images = ["https://imagevault-stage.scandichotels.com.*", "https://imagevault.scandichotels.com.*"] - -[functions] -included_files = ["./.env"] diff --git a/package.json b/package.json index 669ab58da..0565ffa11 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "private": true, "type": "module", "scripts": { - "prebuild": "npm run update-dotenv && npm run lint && npm run test:unit", + "prebuild": "npm run lint && npm run test:unit", "build": "next build", "predev": "rm -rf .next", "dev": "PORT=3000 NEXT_PUBLIC_PORT=3000 next dev", @@ -20,7 +20,6 @@ "test:e2e:headless": "start-server-and-test test:setup http://127.0.0.1:3000/en/sponsoring \"cypress run --e2e\"", "test:setup": "npm run build && npm run start", "preinstall": "export $(cat .env.local | grep -v '^#' | xargs)", - "update-dotenv": "node update-dotenv.mjs", "test:unit": "jest", "test:unit:watch": "jest --watch" }, diff --git a/server/routers/user/utils.ts b/server/routers/user/utils.ts index 7196f389d..cde50270f 100644 --- a/server/routers/user/utils.ts +++ b/server/routers/user/utils.ts @@ -1,4 +1,5 @@ import { metrics } from "@opentelemetry/api" + import { Lang } from "@/constants/languages" import { env } from "@/env/server" import * as api from "@/lib/api" @@ -9,7 +10,9 @@ import type { FriendTransaction, Stay } from "./output" const meter = metrics.getMeter("trpc.user") const getProfileCounter = meter.createCounter("trpc.user.profile") -const getProfileSuccessCounter = meter.createCounter("trpc.user.profile-success") +const getProfileSuccessCounter = meter.createCounter( + "trpc.user.profile-success" +) const getProfileFailCounter = meter.createCounter("trpc.user.profile-fail") async function updateStaysBookingUrl( @@ -41,7 +44,7 @@ async function updateStaysBookingUrl( // Temporary Url, domain and lang support for current web const bookingUrl = new URL( "/hotelreservation/my-booking", - env.PUBLIC_URL ?? "" + env.PUBLIC_URL || "https://www.scandichotels.com" // fallback to production for ephemeral envs (like deploy previews) ) switch (lang) { case Lang.sv: @@ -83,10 +86,7 @@ async function updateStaysBookingUrl( } getProfileSuccessCounter.add(1) - console.info( - "api.user.profile updatebookingurl success", - JSON.stringify({}) - ) + console.info("api.user.profile updatebookingurl success", JSON.stringify({})) return data.map((d) => { const originalString = @@ -98,10 +98,7 @@ async function updateStaysBookingUrl( bookingUrl.searchParams.set("RefId", encryptedBookingValue) } else { bookingUrl.searchParams.set("lastName", apiJson.data.attributes.lastName) - bookingUrl.searchParams.set( - "bookingId", - d.attributes.confirmationNumber - ) + bookingUrl.searchParams.set("bookingId", d.attributes.confirmationNumber) } return { ...d, @@ -113,4 +110,4 @@ async function updateStaysBookingUrl( }) } -export { updateStaysBookingUrl } \ No newline at end of file +export { updateStaysBookingUrl } diff --git a/server/utils.ts b/server/utils.ts index 0179ddf93..0a727c118 100644 --- a/server/utils.ts +++ b/server/utils.ts @@ -1,6 +1,9 @@ import { z } from "zod" import { Lang } from "@/constants/languages" +import { env } from "@/env/server" + +import type { NextRequest } from "next/server" export const langInput = z.object({ lang: z.nativeEnum(Lang), @@ -33,3 +36,27 @@ export function toLang(lang: string): Lang | undefined { const lowerCaseLang = lang.toLowerCase() return Object.values(Lang).find((l) => l === lowerCaseLang) } + +export function getPublicURL(request: NextRequest) { + if (env.PUBLIC_URL) { + return env.PUBLIC_URL + } + + const host = request.nextUrl.host + const proto = request.nextUrl.protocol + return `${proto}//${host}` +} + +export function getPublicNextURL(request: NextRequest) { + if (env.PUBLIC_URL) { + const publicNextURL = request.nextUrl.clone() + // Akamai in front of Netlify for dedicated environments + // require us to rewrite the incoming host and hostname + // to match the public URL used to visit Akamai. + const url = new URL(env.PUBLIC_URL) + publicNextURL.host = url.host + publicNextURL.hostname = url.hostname + return publicNextURL + } + return request.nextUrl +} diff --git a/update-dotenv.mjs b/update-dotenv.mjs deleted file mode 100644 index 6f4521b78..000000000 --- a/update-dotenv.mjs +++ /dev/null @@ -1,71 +0,0 @@ -/** - * Build time environment variables are not available in Netlify functions at - * runtime. The official workaround is to create an artifact and include that - * in the bundled functions so that the function can load/read it at runtime. - * In other words, during the build fill the .env file with the environment - * variables needed and then instruct Netlify to include the .env file together - * with the bundled function. - * - * This works but has two things to consider: - * - * 1. Any environment variable created in the Netlify UI will be considered - * defined. Even if the variable is set to "empty" in the Netlify UI it is - * still an empty string and therefore defined. - * - * 2. Next.js uses @next/env to automatically read the .env - * file into the process environment. @next/env does NOT override any - * defined variables, empty strings are also considered defined. So for - * @next/env to automatically pick up the .env file in the bundled functions - * we need to make sure that none of the variables in the .env file are - * defined in the Netlify UI. @next/env does not have any "override=true" - * option, like dotenv package. So rather than introduce dotenv and manually - * use it in *every* function, we can delegate to @next/env if we keep the - * environment variables in Netlify UI in check. - * - * We only run this on Netlify build. - * - * We define PUBLIC_URL and use that because we are behind Akamai reverse proxy. - * For the stable environments (test, stage, production) these are defined. For - * any other environment (branch deploys and deploy previews) we use the - * predefined Netlify environment variable DEPLOY_PRIME_URL. - * - * Both AUTH_URL and NEXTAUTH_URL is set to point to the PUBLIC_URL. - * We set both as a precaution as next-auth v5 is transitioning to AUTH_* but we - * have seen several occurences in the auth.js codebase that are not using both. - */ - -import fs from "node:fs" - -if (process.env.NETLIFY) { - const PUBLIC_URLS = { - production: "https://www.scandichotels.com", - stage: "https://stage.scandichotels.com", - test: "https://test2.scandichotels.com", - } - - let PUBLIC_URL - if (PUBLIC_URLS[process.env.CONTEXT]) { - PUBLIC_URL = PUBLIC_URLS[process.env.CONTEXT] - } else if (PUBLIC_URLS[process.env.BRANCH]) { - PUBLIC_URL = PUBLIC_URLS[process.env.BRANCH] - } else { - PUBLIC_URL = process.env.DEPLOY_PRIME_URL - } - - const AUTH_URL = `${PUBLIC_URL}/api/web/auth` - const NEXTAUTH_URL = AUTH_URL - - const replaceMap = { - AUTH_URL, - NEXTAUTH_URL, - PUBLIC_URL, - } - - let contents = fs.readFileSync("./.env", { encoding: "utf-8" }) - - for (const [key, value] of Object.entries(replaceMap)) { - contents = contents.replace(new RegExp(`${key}=.*`), `${key}="${value}"`) - } - - fs.writeFileSync("./.env", contents, { encoding: "utf-8" }) -}