import next from 'next'; import Express, { Application, NextFunction, Request, Response } from 'express'; import { createServer } from 'http'; import fs from 'fs'; import path from 'path'; import MobileDetect from 'mobile-detect'; import { initGlobalTracer } from './tracer'; import { getSiteMap } from './sitemap'; import { getHttpLogger } from './log'; import { getRobotsTxt } from './robots'; const port = parseInt(process.env.PORT || '3001', 10); const dev = process.env.NODE_ENV !== 'production'; const app = next({ dev, quiet: !dev }); let configDir = '/app/config'; if (dev) { configDir = path.join(__dirname, '..', 'config'); } const envs = JSON.parse( fs.readFileSync(path.join(configDir, 'envs.json'), 'utf8'), ); // provide device data function deviceMid(request: Request, __: Response, next: NextFunction) { const headers = request.headers; let isMobile: boolean | null = null; try { if (headers['x-is-mobile'] === '1') { isMobile = true; } else if (headers['x-is-mobile'] === '0') { isMobile = false; } if (isMobile === null) { const mobileDetect = new MobileDetect(headers['user-agent'] || ''); isMobile = !!mobileDetect.mobile() && !mobileDetect.tablet(); } (request as any).isMobile = isMobile; (request as any).isBot = headers['x-is-bot'] === '1'; next(); } catch (e: any) { // TODO: replace with proper logger (request as any).log.error(e); next(); } } // inject environment variables from envs.json function envMid(request: Request, __: Response, next: NextFunction) { try { // provide access to env variables (request as any).envs = envs; next(); } catch (e: any) { // TODO: replace with proper logger (request as any).log.error(e); next(); } } export function getApp(app: any) { const router = Express.Router(); const nextHandler = app.getRequestHandler(); const landingHandler = async (req: Request, res: Response, slug: string) => { return await app.render(req, res, slug); }; router.get('/', (req, res) => { return landingHandler(req, res, '/'); }); router.get('/check-status', (req, res) => { return res.send({ code: (req as any).envs.DOMAIN_VERIFICATION_CODE }); }); router.get('/sitemap.xml', getSiteMap); router.get('/robots.txt', getRobotsTxt); router.get( `/:lang(${envs.REGEX_LANGUAGE_CODE})/:slug([a-zA-Z0-9-]+)`, (req, res) => { return landingHandler( req, res, `/multiLang/${req.params.lang}/${req.params.slug}`, ); }, ); router.get(`/:lang(${envs.REGEX_LANGUAGE_CODE})`, (req, res) => { return landingHandler(req, res, `/multiLang/${req.params.lang}`); }); router.get('/:slug([a-zA-Z0-9-]+)', (req, res) => { return landingHandler(req, res, `/default/${req.params.slug}`); }); router.all('*', (req, res) => { return nextHandler(req, res); }); return router; } app.prepare().then(async () => { initGlobalTracer('tempi-landing', { endpoint: process.env.JAEGER_COLLECTOR_URL, }); const express: Application = Express(); express.use(getHttpLogger({})); express.use(envMid); express.use(deviceMid); express.use(getApp(app)); if (dev) { createServer(express).listen(port, () => { console.info( `Server listening at http://localhost:${port} as ${ dev ? 'development' : process.env.NODE_ENV }`, ); }); } else { // app.setAssetPrefix('https://landing-beta.teko.vn'); express.listen(port, () => { console.info( `Server listening at http://localhost:${port} as ${ dev ? 'development' : process.env.NODE_ENV }`, ); }); } });