From 050268f73866a402638ed308749b6f5b9ca08c0e Mon Sep 17 00:00:00 2001 From: Geoffroy Empain Date: Mon, 7 Dec 2020 11:10:37 +0100 Subject: [PATCH] feat: redirect 404 to each site /404.html --- src/caddy/config/errors.ts | 38 ------------------- src/caddy/config/generate-site-routes.ts | 11 ++---- src/caddy/config/get-error-routes.ts | 44 ++++++++++++++++++++++ src/caddy/config/get-site-error-routes.ts | 44 ++++++++++++++++++++++ src/caddy/generate-config.ts | 4 +- src/caddy/utils/get-branch-dir-in-caddy.ts | 9 +++++ 6 files changed, 103 insertions(+), 47 deletions(-) delete mode 100644 src/caddy/config/errors.ts create mode 100644 src/caddy/config/get-error-routes.ts create mode 100644 src/caddy/config/get-site-error-routes.ts create mode 100644 src/caddy/utils/get-branch-dir-in-caddy.ts diff --git a/src/caddy/config/errors.ts b/src/caddy/config/errors.ts deleted file mode 100644 index ff5fd65..0000000 --- a/src/caddy/config/errors.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { env } from '../../env'; -import { getReverseProxyDial } from '../utils/get-reverse-proxy-dial'; - -export const errors = { - routes: [ - // https://caddy.community/t/v2-need-help-with-the-json-configuration-for-custom-404-and-redirects/7059/13 - { - handle: [{ - handler: 'vars', - status_code: '{http.error.status_code}', - }], - }, - { - match: [{ - vars: { - status_code: '404', - }, - }], - handle: [ - { - handler: 'rewrite', - uri: '/static/404.html', - }, - // https://caddyserver.com/docs/json/apps/http/servers/routes/handle/reverse_proxy/ - { - handler: 'reverse_proxy', - upstreams: [{ - dial: getReverseProxyDial(env.MELI_URL_INTERNAL.toString()), - }], - handle_response: [{ - status_code: '{http.error.status_code}', - }], - }, - ], - terminal: true, - }, - ], -}; diff --git a/src/caddy/config/generate-site-routes.ts b/src/caddy/config/generate-site-routes.ts index 19dd384..261fda8 100644 --- a/src/caddy/config/generate-site-routes.ts +++ b/src/caddy/config/generate-site-routes.ts @@ -1,17 +1,14 @@ -import { - AcmeSslConfiguration, Site, SiteDomain, -} from '../../entities/sites/site'; +import { AcmeSslConfiguration, Site, SiteDomain } from '../../entities/sites/site'; import { env } from '../../env'; import { unique } from '../../utils/arrays-utils'; import { RedirectType, ReverseProxyRedirectConfig } from '../../entities/sites/redirect'; import { relative, resolve } from 'path'; -import { - getBranchFilesDir, getBranchStaticDir, getFileRedirectFileName, -} from '../../entities/sites/get-site-dir'; +import { getBranchFilesDir, getFileRedirectFileName } from '../../entities/sites/get-site-dir'; import { URL } from 'url'; import { getReverseProxyDial } from '../utils/get-reverse-proxy-dial'; import { BranchPassword } from '../../entities/sites/branch'; import { base64Encode } from '../../commons/utils/base64'; +import { getBranchDirInCaddy } from '../utils/get-branch-dir-in-caddy'; const sitesUrl = new URL(env.MELI_SITES_URL); @@ -94,7 +91,7 @@ export function generateSiteRoutes(site: Site): any[] { }], handle: [{ handler: 'file_server', - root: resolve(env.MELI_CADDY_DIR, relative(env.MELI_SITES_DIR, getBranchStaticDir(site._id, branch))), + root: getBranchDirInCaddy(site._id, branch), }], terminal: true, }, diff --git a/src/caddy/config/get-error-routes.ts b/src/caddy/config/get-error-routes.ts new file mode 100644 index 0000000..84ed954 --- /dev/null +++ b/src/caddy/config/get-error-routes.ts @@ -0,0 +1,44 @@ +import { env } from '../../env'; +import { getReverseProxyDial } from '../utils/get-reverse-proxy-dial'; +import { Site } from '../../entities/sites/site'; +import { getSiteErrorRoutes } from './get-site-error-routes'; + +export function getErrorRoutes(sites: Site[]) { + return { + routes: [ + // https://caddy.community/t/v2-need-help-with-the-json-configuration-for-custom-404-and-redirects/7059/13 + { + handle: [{ + handler: 'vars', + status_code: '{http.error.status_code}', + }], + }, + ...sites.flatMap(getSiteErrorRoutes), + // fallback + { + match: [{ + vars: { + status_code: '404', + }, + }], + handle: [ + { + handler: 'rewrite', + uri: '/static/404.html', + }, + // https://caddyserver.com/docs/json/apps/http/servers/routes/handle/reverse_proxy/ + { + handler: 'reverse_proxy', + upstreams: [{ + dial: getReverseProxyDial(env.MELI_URL_INTERNAL.toString()), + }], + handle_response: [{ + status_code: '{http.error.status_code}', + }], + }, + ], + terminal: true, + }, + ], + }; +} diff --git a/src/caddy/config/get-site-error-routes.ts b/src/caddy/config/get-site-error-routes.ts new file mode 100644 index 0000000..f7db71e --- /dev/null +++ b/src/caddy/config/get-site-error-routes.ts @@ -0,0 +1,44 @@ +import { Site } from '../../entities/sites/site'; +import { URL } from 'url'; +import { env } from '../../env'; +import { getBranchDirInCaddy } from '../utils/get-branch-dir-in-caddy'; + +const sitesUrl = new URL(env.MELI_SITES_URL); + +export function getSiteErrorRoutes(site: Site) { + return site.branches.map(branch => { + const hosts = [ + `${branch.slug}.${site.name}.${sitesUrl.host}`, + ...site.domains.map(domain => `${branch.slug}.${domain.name}`), + ]; + if (site.mainBranch === branch._id) { + hosts.push(`${site.name}.${sitesUrl.host}`); + hosts.push(...site.domains.map(domain => domain.name)); + } + const branchDir = getBranchDirInCaddy(site._id, branch); + return getErrorRoute(hosts, branchDir); + }); +} + +function getErrorRoute(hosts: string[], rootDir: string) { + return { + match: [{ + vars: { + status_code: '404', + }, + host: hosts, + }], + handle: [ + { + handler: 'rewrite', + uri: '/404.html', + }, + // https://caddyserver.com/docs/json/apps/http/servers/routes/handle/reverse_proxy/ + { + handler: 'file_server', + root: rootDir, + }, + ], + terminal: true, + }; +} diff --git a/src/caddy/generate-config.ts b/src/caddy/generate-config.ts index df42a10..950671d 100644 --- a/src/caddy/generate-config.ts +++ b/src/caddy/generate-config.ts @@ -1,7 +1,7 @@ import { Sites } from '../entities/sites/site'; import { env } from '../env'; import { generateSiteRoutes } from './config/generate-site-routes'; -import { errors } from './config/errors'; +import { getErrorRoutes } from './config/get-error-routes'; import { generateManualCertificatesConfig, generateServerTlsConfig } from './config/ssl'; import { uiRoute } from './config/ui-route'; import { apiRoute } from './config/api-route'; @@ -35,7 +35,7 @@ export async function generateConfig(): Promise { uiRoute, ...sites.flatMap(generateSiteRoutes), ], - errors, + errors: getErrorRoutes(sites), ...(sslDisabled ? [] : generateServerTlsConfig(sites)), }, }, diff --git a/src/caddy/utils/get-branch-dir-in-caddy.ts b/src/caddy/utils/get-branch-dir-in-caddy.ts new file mode 100644 index 0000000..dd8b0c3 --- /dev/null +++ b/src/caddy/utils/get-branch-dir-in-caddy.ts @@ -0,0 +1,9 @@ +import { relative, resolve } from 'path'; +import { env } from '../../env'; +import { getBranchStaticDir } from '../../entities/sites/get-site-dir'; +import { Branch } from '../../entities/sites/branch'; + +export function getBranchDirInCaddy(siteId: string, branch: Branch) { + const branchStaticDir = getBranchStaticDir(siteId, branch); + return resolve(env.MELI_CADDY_DIR, relative(env.MELI_SITES_DIR, branchStaticDir)); +}