Merged PR 1674: Language switching issues
Related work items: #16185, #16630
This commit is contained in:
@@ -36,3 +36,6 @@ pages/polling.js
|
|||||||
# dev apis to no include
|
# dev apis to no include
|
||||||
|
|
||||||
pages/api/endpoint/getaccounts_api.js
|
pages/api/endpoint/getaccounts_api.js
|
||||||
|
|
||||||
|
# certs
|
||||||
|
certificates/*
|
||||||
|
|||||||
@@ -2144,3 +2144,19 @@ export const createCRMTask = async (formValues) => {
|
|||||||
consoleLogger(error);
|
consoleLogger(error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getPreferredLanguage = async (email) => {
|
||||||
|
return axios
|
||||||
|
.get(
|
||||||
|
BASE_URL +
|
||||||
|
"/api/endpoint/getpreferredlanguage_api?emailAddress=" +
|
||||||
|
email
|
||||||
|
)
|
||||||
|
.then((res) => {
|
||||||
|
return res.data;
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
consoleLogger(error);
|
||||||
|
return error.response;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { useRouter } from "next/router";
|
|||||||
import React, { useEffect } from "react";
|
import React, { useEffect } from "react";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { updateAccount } from "../../actions";
|
import { updateAccount } from "../../actions";
|
||||||
|
import { setCookie } from "nookies";
|
||||||
|
|
||||||
const PersonalDetailsComplete = (props) => {
|
const PersonalDetailsComplete = (props) => {
|
||||||
const {
|
const {
|
||||||
@@ -17,14 +18,39 @@ const PersonalDetailsComplete = (props) => {
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { locale } = router;
|
const { locale } = router;
|
||||||
|
|
||||||
|
// let contactid = props.accountDetails.loggedinUserId;
|
||||||
|
// let updateBody = props.props.props.form.personalDetailsForm.values;
|
||||||
|
// let prefLang =
|
||||||
|
// props.props.props.form.personalDetailsForm.values
|
||||||
|
// .pinswg_preferredlanguage;
|
||||||
|
|
||||||
|
const { loggedinUserId } = props.accountDetails || {};
|
||||||
|
const formValues = props.props?.props?.form?.personalDetailsForm?.values;
|
||||||
|
const prefLang = formValues?.pinswg_preferredlanguage;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let contactid = props.accountDetails.loggedinUserId;
|
// let contactid = props.accountDetails.loggedinUserId;
|
||||||
let updateBody = props.props.props.form.personalDetailsForm.values;
|
// let updateBody = props.props.props.form.personalDetailsForm.values;
|
||||||
updateAccount(contactid, updateBody);
|
// let prefLang =
|
||||||
}, [
|
// props.props.props.form.personalDetailsForm.values
|
||||||
props.accountDetails.loggedinUserId,
|
// .pinswg_preferredlanguage;
|
||||||
props.props.props.form.personalDetailsForm.values,
|
if (!loggedinUserId || !formValues) return;
|
||||||
]);
|
|
||||||
|
console.log("=============== pref lang", prefLang);
|
||||||
|
const userLang = prefLang == "846040000" ? "cy" : "en";
|
||||||
|
setCookie(null, "pedw_locale", userLang, {
|
||||||
|
path: "/",
|
||||||
|
maxAge: 60 * 60 * 24 * 365,
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("Set cookie to:", userLang);
|
||||||
|
|
||||||
|
async function doUpdate() {
|
||||||
|
const response = await updateAccount(loggedinUserId, formValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
doUpdate();
|
||||||
|
}, [loggedinUserId, formValues, prefLang]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -33,10 +59,7 @@ const PersonalDetailsComplete = (props) => {
|
|||||||
{/* <p className="govuk-body">{t("account:account-complete-para-2")}</p> */}
|
{/* <p className="govuk-body">{t("account:account-complete-para-2")}</p> */}
|
||||||
|
|
||||||
<p className="govuk-body">
|
<p className="govuk-body">
|
||||||
<Link
|
<Link href={"/"} className="govuk-link">
|
||||||
href={"/myportal?q=" + props.accountDetails.loggedinUserId}
|
|
||||||
className="govuk-link"
|
|
||||||
>
|
|
||||||
{" "}
|
{" "}
|
||||||
{t("account:account-complete-return-to-portal-link")}
|
{t("account:account-complete-return-to-portal-link")}
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@@ -14,80 +14,9 @@ import { PrismaAdapter } from "@next-auth/prisma-adapter";
|
|||||||
import { PrismaClient } from "@prisma/client";
|
import { PrismaClient } from "@prisma/client";
|
||||||
import NextAuth from "next-auth";
|
import NextAuth from "next-auth";
|
||||||
import EmailProvider from "next-auth/providers/email";
|
import EmailProvider from "next-auth/providers/email";
|
||||||
import { consoleLogger } from "../../../actions";
|
import { consoleLogger, getPreferredLanguage } from "../../../actions";
|
||||||
|
|
||||||
const prisma = new PrismaClient();
|
const prisma = new PrismaClient();
|
||||||
// For more information on each option (and a full list of options) go to
|
|
||||||
// https://next-auth.js.org/configuration/options
|
|
||||||
// export default NextAuth({
|
|
||||||
// // https://next-auth.js.org/configuration/providers
|
|
||||||
// providers: [
|
|
||||||
// EmailProvider({
|
|
||||||
// // server: {
|
|
||||||
// // host: process.env.EMAIL_SERVER_HOST,
|
|
||||||
// // port: process.env.EMAIL_SERVER_PORT,
|
|
||||||
// // auth: {
|
|
||||||
// // user: process.env.EMAIL_SERVER_USER,
|
|
||||||
// // pass: process.env.EMAIL_SERVER_PASSWORD,
|
|
||||||
// // },
|
|
||||||
// // },
|
|
||||||
// // from: process.env.EMAIL_FROM,
|
|
||||||
// maxAge: 10 * 60, // Magic links are valid for 10 min only
|
|
||||||
// async sendVerificationRequest({
|
|
||||||
// identifier: email,
|
|
||||||
// url,
|
|
||||||
// provider: { server, from },
|
|
||||||
// }) {
|
|
||||||
// const { host } = new URL(url);
|
|
||||||
// const templateId = "b1b5704b-9bb8-4deb-a75c-d887ca902661";
|
|
||||||
// const emailAddress = email;
|
|
||||||
// const personalisation = {
|
|
||||||
// "emailAddress": email,
|
|
||||||
// "signInLink": url,
|
|
||||||
// "linkExpiry": 10 * 60,
|
|
||||||
// };
|
|
||||||
// const reference = "PEDW-SIGNIN";
|
|
||||||
|
|
||||||
// var NotifyClient =
|
|
||||||
// require("notifications-node-client").NotifyClient;
|
|
||||||
|
|
||||||
// const notifyClient = new NotifyClient(
|
|
||||||
// process.env.NOTIFY_API_KEY
|
|
||||||
// );
|
|
||||||
|
|
||||||
// await notifyClient
|
|
||||||
// .sendEmail(templateId, emailAddress, {
|
|
||||||
// personalisation: personalisation,
|
|
||||||
// reference: reference,
|
|
||||||
// // emailReplyToId: emailReplyToId,
|
|
||||||
// })
|
|
||||||
// //.then((response) => console.log(response))
|
|
||||||
// .catch((error) => consoleLogger(err));
|
|
||||||
// },
|
|
||||||
// }),
|
|
||||||
// ],
|
|
||||||
// adapter: PrismaAdapter(prisma),
|
|
||||||
// secret: process.env.SECRET,
|
|
||||||
// session: {
|
|
||||||
// jwt: true,
|
|
||||||
// pages: {},
|
|
||||||
// theme: "dark",
|
|
||||||
// debug: true,
|
|
||||||
// },
|
|
||||||
// pages: {
|
|
||||||
// signIn: "/auth/signin",
|
|
||||||
// //signOut: "/auth/signout",
|
|
||||||
// error: "/auth/error", // Error code passed in query string as ?error=
|
|
||||||
// verifyRequest: "/auth/verify-request", // (used for check email message)
|
|
||||||
// newUser: "/account/register", // New users will be directed here on first sign in (leave the property out if not of interest)
|
|
||||||
// },
|
|
||||||
// callbacks: {
|
|
||||||
// session: async (session, user) => {
|
|
||||||
// //console.log(user);
|
|
||||||
// return Promise.resolve(session);
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// });
|
|
||||||
|
|
||||||
const parseUrl = (url) => {
|
const parseUrl = (url) => {
|
||||||
const defaultUrl = new URL(
|
const defaultUrl = new URL(
|
||||||
@@ -169,7 +98,9 @@ const authOptions = (locale, req, res) => {
|
|||||||
"&token=" +
|
"&token=" +
|
||||||
searchParams.get("token") +
|
searchParams.get("token") +
|
||||||
"&email=" +
|
"&email=" +
|
||||||
encodeURIComponent(email)
|
encodeURIComponent(email) +
|
||||||
|
"&locale=" +
|
||||||
|
effectiveLocale
|
||||||
: url;
|
: url;
|
||||||
|
|
||||||
let formURL = appendParamsAndPathToNewUrl(url, newURL);
|
let formURL = appendParamsAndPathToNewUrl(url, newURL);
|
||||||
@@ -191,23 +122,43 @@ const authOptions = (locale, req, res) => {
|
|||||||
const { host, port, protocol, token, searchParams } =
|
const { host, port, protocol, token, searchParams } =
|
||||||
new URL(url);
|
new URL(url);
|
||||||
|
|
||||||
|
const baseDomain = `${protocol}//${host}`;
|
||||||
const templateId = "b1b5704b-9bb8-4deb-a75c-d887ca902661";
|
const templateId = "b1b5704b-9bb8-4deb-a75c-d887ca902661";
|
||||||
const templateIdcy = "0614ce53-cd5f-421f-a1a5-8c8486a9113a";
|
const templateIdcy = "0614ce53-cd5f-421f-a1a5-8c8486a9113a";
|
||||||
const emailAddress = email;
|
const emailAddress = email;
|
||||||
|
|
||||||
|
const queryLocale = req?.query?.locale || req?.body?.locale;
|
||||||
|
const cookieLocale = req.cookies["pedw_locale"];
|
||||||
|
let locale = queryLocale || cookieLocale || "en";
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
"============================================================\n",
|
"============================================================\n",
|
||||||
"verification url----: " + url + "\n",
|
"verification url----: " + url + "\n",
|
||||||
"============================================================\n"
|
"============================================================\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const prefLang = await getPreferredLanguage(emailAddress);
|
||||||
|
|
||||||
|
const registeredPrefLanguage =
|
||||||
|
prefLang.value.length > 0
|
||||||
|
? prefLang.value[0].pinswg_preferredlanguage ===
|
||||||
|
846040000
|
||||||
|
? "cy"
|
||||||
|
: "en"
|
||||||
|
: "en";
|
||||||
|
|
||||||
|
const effectiveLocale = registeredPrefLanguage ?? locale;
|
||||||
let newURL =
|
let newURL =
|
||||||
locale == "cy"
|
effectiveLocale == "cy"
|
||||||
? process.env.CY_API_ROOT +
|
? baseDomain +
|
||||||
"/api/auth/callback/email?callbackUrl=" +
|
"/api/auth/callback/email?callbackUrl=" +
|
||||||
encodeURIComponent(process.env.CY_API_ROOT) +
|
encodeURIComponent(baseDomain + "/cy") +
|
||||||
"&token=" +
|
"&token=" +
|
||||||
searchParams.get("token") +
|
searchParams.get("token") +
|
||||||
"&email=" +
|
"&email=" +
|
||||||
encodeURIComponent(email)
|
encodeURIComponent(email) +
|
||||||
|
"&locale=" +
|
||||||
|
effectiveLocale
|
||||||
: url;
|
: url;
|
||||||
|
|
||||||
let formURL = appendParamsAndPathToNewUrl(url, newURL);
|
let formURL = appendParamsAndPathToNewUrl(url, newURL);
|
||||||
@@ -240,7 +191,7 @@ const authOptions = (locale, req, res) => {
|
|||||||
|
|
||||||
await notifyClient
|
await notifyClient
|
||||||
.sendEmail(
|
.sendEmail(
|
||||||
locale == "cy" ? templateIdcy : templateId,
|
effectiveLocale == "cy" ? templateIdcy : templateId,
|
||||||
emailAddress,
|
emailAddress,
|
||||||
{
|
{
|
||||||
personalisation: personalisation,
|
personalisation: personalisation,
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
/**
|
||||||
|
* @swagger
|
||||||
|
* /api/endpoint/getemailaccountcheck_api:
|
||||||
|
* get:
|
||||||
|
* tags: [Login]
|
||||||
|
* description: Returns portal login
|
||||||
|
* summary: Phase 2
|
||||||
|
* parameters:
|
||||||
|
* - name: emailAddress
|
||||||
|
* in: query
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: hello world
|
||||||
|
*/
|
||||||
|
import axios from "axios";
|
||||||
|
import CryptoJS from "crypto-js";
|
||||||
|
import _ from "lodash";
|
||||||
|
import {
|
||||||
|
azureHeaders,
|
||||||
|
consoleLogger,
|
||||||
|
getToken,
|
||||||
|
getPreferredLanguage,
|
||||||
|
} from "../../../actions";
|
||||||
|
|
||||||
|
const WORDKEY = process.env.HASHKEY;
|
||||||
|
|
||||||
|
const WEBAPI_URL =
|
||||||
|
process.env.RELAY_ROOT ||
|
||||||
|
"https://dev-pedw-ns.servicebus.windows.net/dev-pedw-hc/";
|
||||||
|
|
||||||
|
const hashAPIPath = (queryPath) => {
|
||||||
|
var hashlink = CryptoJS.HmacSHA256(
|
||||||
|
queryPath,
|
||||||
|
CryptoJS.enc.Hex.parse(WORDKEY)
|
||||||
|
);
|
||||||
|
hashlink = hashlink.toString(CryptoJS.enc.Hex);
|
||||||
|
return (queryPath.indexOf("?") > -1 ? "&hash=" : "?hash=") + hashlink;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default async function ApiProxy(req, res) {
|
||||||
|
var emailAddress = req.query.emailAddress;
|
||||||
|
var token = await getToken();
|
||||||
|
|
||||||
|
var queryUrl =
|
||||||
|
"contacts?$filter=emailaddress1 eq '" +
|
||||||
|
emailAddress +
|
||||||
|
"'&$count=true&$select=pinswg_preferredlanguage,contactid";
|
||||||
|
|
||||||
|
console.log(queryUrl);
|
||||||
|
// var queryUrl = "contacts/?$count=true&$select=emailaddress1, contactid";
|
||||||
|
|
||||||
|
var apiResponse = _.isEmpty(req.query)
|
||||||
|
? res.status(400).json()
|
||||||
|
: typeof emailAddress != "undefined" && emailAddress.length > 0
|
||||||
|
? axios
|
||||||
|
.get(
|
||||||
|
WEBAPI_URL + queryUrl + hashAPIPath(queryUrl),
|
||||||
|
azureHeaders(token.access_token)
|
||||||
|
)
|
||||||
|
.then(({ data }) => {
|
||||||
|
res.status(200).json(data);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
consoleLogger(error);
|
||||||
|
res.status(400).json(error);
|
||||||
|
})
|
||||||
|
: res.status(400).json();
|
||||||
|
|
||||||
|
return apiResponse;
|
||||||
|
}
|
||||||
@@ -7,6 +7,8 @@ import CookieBanner from "../../components/cookieBanner";
|
|||||||
import Footer from "../../components/footer";
|
import Footer from "../../components/footer";
|
||||||
import Header from "../../components/header";
|
import Header from "../../components/header";
|
||||||
import ServiceBanner from "../../components/servicebanner";
|
import ServiceBanner from "../../components/servicebanner";
|
||||||
|
import { destroyCookie, setCookie } from "nookies";
|
||||||
|
import { useEffect } from "react";
|
||||||
|
|
||||||
import { getCsrfToken } from "next-auth/react";
|
import { getCsrfToken } from "next-auth/react";
|
||||||
|
|
||||||
@@ -16,6 +18,14 @@ const Error = (props) => {
|
|||||||
|
|
||||||
const { error } = useRouter().query;
|
const { error } = useRouter().query;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
window.localStorage.clear(),
|
||||||
|
destroyCookie(null, "next-auth.csrf-token", { path: "/" }),
|
||||||
|
destroyCookie(null, "next-auth.callback-url", { path: "/" }),
|
||||||
|
destroyCookie(null, "pedw_locale", { path: "/" }),
|
||||||
|
destroyCookie(null, "pinsUser", { path: "/" });
|
||||||
|
}, []);
|
||||||
|
|
||||||
const errors = {
|
const errors = {
|
||||||
Signin: t("auth:auth-error-Signin-label"),
|
Signin: t("auth:auth-error-Signin-label"),
|
||||||
OAuthSignin: t("auth:auth-error-OAuthSignin-label"),
|
OAuthSignin: t("auth:auth-error-OAuthSignin-label"),
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import CookieBanner from "../../components/cookieBanner";
|
|||||||
import Footer from "../../components/footer";
|
import Footer from "../../components/footer";
|
||||||
import Header from "../../components/header";
|
import Header from "../../components/header";
|
||||||
import ServiceBanner from "../../components/servicebanner";
|
import ServiceBanner from "../../components/servicebanner";
|
||||||
|
import { getPreferredLanguage } from "../../actions";
|
||||||
|
import { setCookie } from "nookies";
|
||||||
|
|
||||||
const SignIn = (props) => {
|
const SignIn = (props) => {
|
||||||
let { t, lang } = useTranslation();
|
let { t, lang } = useTranslation();
|
||||||
@@ -25,6 +27,35 @@ const SignIn = (props) => {
|
|||||||
const handleSubmit = async (event) => {
|
const handleSubmit = async (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
setButtonDisabled(true);
|
setButtonDisabled(true);
|
||||||
|
|
||||||
|
const email = event.target.email.value;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await getPreferredLanguage(encodeURIComponent(email));
|
||||||
|
const data = await res;
|
||||||
|
|
||||||
|
const userLang =
|
||||||
|
data.value.length > 0
|
||||||
|
? data.value[0].pinswg_preferredlanguage === 846040000
|
||||||
|
? "cy"
|
||||||
|
: "en"
|
||||||
|
: "en";
|
||||||
|
|
||||||
|
// Modify callbackUrl hidden input to add/update lang param
|
||||||
|
const url = new URL(event.target.callbackUrl.value);
|
||||||
|
url.searchParams.set("locale", userLang);
|
||||||
|
|
||||||
|
setCookie(null, "pedw_locale", userLang, {
|
||||||
|
path: "/",
|
||||||
|
maxAge: 60 * 60 * 24 * 365,
|
||||||
|
});
|
||||||
|
|
||||||
|
event.target.callbackUrl.value = url.toString();
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to get preferred language", error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Submit form after updating callbackUrl
|
||||||
event.target.submit();
|
event.target.submit();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -15,7 +15,7 @@ import {
|
|||||||
touch,
|
touch,
|
||||||
SubmissionError,
|
SubmissionError,
|
||||||
} from "redux-form";
|
} from "redux-form";
|
||||||
import { connect, submitError } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { createCRMTask, sendEmail } from "../actions";
|
import { createCRMTask, sendEmail } from "../actions";
|
||||||
|
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
@@ -527,7 +527,7 @@ export default connect(
|
|||||||
destroyOnUnmount: false,
|
destroyOnUnmount: false,
|
||||||
touchOnBlur: true,
|
touchOnBlur: true,
|
||||||
touchOnChange: true,
|
touchOnChange: true,
|
||||||
onSubmitFail: (errors, dispatch, subnittError, props) => {
|
onSubmitFail: (errors, dispatch, submitError, props) => {
|
||||||
if (errors) {
|
if (errors) {
|
||||||
// Touch all fields with errors so validation messages appear
|
// Touch all fields with errors so validation messages appear
|
||||||
const errorFields = Object.keys(errors);
|
const errorFields = Object.keys(errors);
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import {
|
|||||||
touch,
|
touch,
|
||||||
SubmissionError,
|
SubmissionError,
|
||||||
} from "redux-form";
|
} from "redux-form";
|
||||||
import { connect, submitError } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { createCRMTask, sendEmail } from "../../actions";
|
import { createCRMTask, sendEmail } from "../../actions";
|
||||||
|
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
@@ -528,7 +528,7 @@ export default connect(
|
|||||||
destroyOnUnmount: false,
|
destroyOnUnmount: false,
|
||||||
touchOnBlur: true,
|
touchOnBlur: true,
|
||||||
touchOnChange: true,
|
touchOnChange: true,
|
||||||
onSubmitFail: (errors, dispatch, subnittError, props) => {
|
onSubmitFail: (errors, dispatch, submitError, props) => {
|
||||||
if (errors) {
|
if (errors) {
|
||||||
// Touch all fields with errors so validation messages appear
|
// Touch all fields with errors so validation messages appear
|
||||||
const errorFields = Object.keys(errors);
|
const errorFields = Object.keys(errors);
|
||||||
|
|||||||
@@ -222,9 +222,7 @@ export const getServerSideProps = wrapper.getServerSideProps(
|
|||||||
|
|
||||||
// Determine preferred locale (cookie overrides)
|
// Determine preferred locale (cookie overrides)
|
||||||
let preferredLocale =
|
let preferredLocale =
|
||||||
accountDetails.pinswg_preferredlanguage === "846040000"
|
accountDetails.pinswg_preferredlanguage === 846040000 ? "cy" : "en";
|
||||||
? "cy"
|
|
||||||
: "en";
|
|
||||||
if (cookies.pedw_locale) {
|
if (cookies.pedw_locale) {
|
||||||
preferredLocale = cookies.pedw_locale;
|
preferredLocale = cookies.pedw_locale;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
const next = require("next");
|
const next = require("next");
|
||||||
const { createServer } = require("http");
|
const { createServer: createHttpServer } = require("http");
|
||||||
|
const { createServer: createHttpsServer } = require("https");
|
||||||
|
const fs = require("fs");
|
||||||
|
const path = require("path");
|
||||||
const appInsights = require("applicationinsights");
|
const appInsights = require("applicationinsights");
|
||||||
|
|
||||||
const initAppInsights = (instrumentationKey) => {
|
const initAppInsights = (instrumentationKey) => {
|
||||||
@@ -26,44 +29,75 @@ const startServer = async (config) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const app = next(serverOptions);
|
const app = next(serverOptions);
|
||||||
await app.prepare(); // prepare BEFORE starting the server
|
await app.prepare();
|
||||||
|
|
||||||
const handleNextRequests = app.getRequestHandler();
|
const handleNextRequests = app.getRequestHandler();
|
||||||
|
|
||||||
const srv = createServer((req, res) => {
|
const httpsOptions = {
|
||||||
|
key: fs.readFileSync(
|
||||||
|
path.join(__dirname, "certificates", "cert-key.pem")
|
||||||
|
),
|
||||||
|
cert: fs.readFileSync(path.join(__dirname, "certificates", "cert.pem")),
|
||||||
|
};
|
||||||
|
|
||||||
|
// HTTPS server on port 3000
|
||||||
|
const httpsServer = createHttpsServer(httpsOptions, (req, res) => {
|
||||||
if (config.useAppInsights) {
|
if (config.useAppInsights) {
|
||||||
appInsights.defaultClient.trackNodeHttpRequest({
|
appInsights.defaultClient.trackNodeHttpRequest({
|
||||||
request: req,
|
request: req,
|
||||||
response: res,
|
response: res,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
handleNextRequests(req, res);
|
handleNextRequests(req, res);
|
||||||
});
|
});
|
||||||
|
|
||||||
await new Promise((resolve, reject) => {
|
// HTTP server on port 3001 for redirect
|
||||||
srv.on("error", reject);
|
const httpServer = createHttpServer((req, res) => {
|
||||||
srv.on("listening", () => resolve());
|
const host = req.headers.host?.split(":")[0] || "localhost";
|
||||||
srv.listen(config.port, config.hostname);
|
res.writeHead(301, {
|
||||||
|
Location: `https://${host}:3000${req.url}`,
|
||||||
|
});
|
||||||
|
res.end();
|
||||||
|
});
|
||||||
|
|
||||||
|
await new Promise((resolve, reject) => {
|
||||||
|
httpsServer.on("error", reject);
|
||||||
|
httpsServer.on("listening", () => {
|
||||||
|
console.log(`HTTPS server listening on port ${config.port}`);
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
httpsServer.listen(config.port, config.hostname);
|
||||||
|
});
|
||||||
|
|
||||||
|
await new Promise((resolve, reject) => {
|
||||||
|
httpServer.on("error", reject);
|
||||||
|
httpServer.on("listening", () => {
|
||||||
|
console.log(
|
||||||
|
`HTTP server listening on port ${config.httpPort} (redirecting to HTTPS)`
|
||||||
|
);
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
httpServer.listen(config.httpPort, config.hostname);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Graceful shutdown handling
|
|
||||||
process.on("SIGTERM", () => {
|
process.on("SIGTERM", () => {
|
||||||
console.log("Received SIGTERM, shutting down gracefully...");
|
console.log("Received SIGTERM, shutting down gracefully...");
|
||||||
srv.close(() => {
|
httpsServer.close(() => {
|
||||||
console.log("Server closed.");
|
httpServer.close(() => {
|
||||||
process.exit(0);
|
console.log("Servers closed.");
|
||||||
|
process.exit(0);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
return app;
|
return app;
|
||||||
};
|
};
|
||||||
|
|
||||||
// App configuration
|
|
||||||
const startTime = Date.now();
|
const startTime = Date.now();
|
||||||
const serverConfig = {
|
const serverConfig = {
|
||||||
hostname: "0.0.0.0", // Required for Azure App Service
|
hostname: "0.0.0.0",
|
||||||
port: parseInt(process.env.PORT, 10) || 3000,
|
port: 3000, // HTTPS port
|
||||||
|
httpPort: 3001, // HTTP redirect port
|
||||||
env: process.env.APP_ENV || process.env.NODE_ENV || "production",
|
env: process.env.APP_ENV || process.env.NODE_ENV || "production",
|
||||||
useAppInsights: initAppInsights(
|
useAppInsights: initAppInsights(
|
||||||
process.env.NEXT_PUBLIC_APPINSIGHTS_INSTRUMENTATIONKEY
|
process.env.NEXT_PUBLIC_APPINSIGHTS_INSTRUMENTATIONKEY
|
||||||
@@ -73,7 +107,7 @@ const serverConfig = {
|
|||||||
startServer(serverConfig)
|
startServer(serverConfig)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
console.log(
|
console.log(
|
||||||
`Server ready on http://${serverConfig.hostname}:${serverConfig.port} [${serverConfig.env}]`
|
`Server ready on https://${serverConfig.hostname}:${serverConfig.port} [${serverConfig.env}]`
|
||||||
);
|
);
|
||||||
|
|
||||||
if (serverConfig.useAppInsights) {
|
if (serverConfig.useAppInsights) {
|
||||||
|
|||||||
Reference in New Issue
Block a user