feat(pockethost): sass custom domains support

This commit is contained in:
Ben Allfree 2024-07-23 21:01:15 +00:00
parent d687fcf98a
commit 4d5bccdfcb
3 changed files with 52 additions and 9 deletions

View File

@ -16,10 +16,12 @@
"esbuild", "esbuild",
"eventsource", "eventsource",
"fullchain", "fullchain",
"geoip",
"getenv", "getenv",
"gobot", "gobot",
"goja", "goja",
"IPCIDR", "IPCIDR",
"ipcountry",
"jsonifiable", "jsonifiable",
"Jsonifiable", "Jsonifiable",
"lemonbot", "lemonbot",

View File

@ -107,6 +107,7 @@ export const SETTINGS = {
PH_FTP_PASV_PORT_MIN: mkNumber(10000), PH_FTP_PASV_PORT_MIN: mkNumber(10000),
PH_FTP_PASV_PORT_MAX: mkNumber(20000), PH_FTP_PASV_PORT_MAX: mkNumber(20000),
EDGE_SASS_DOMAINS_AUTH_TOKEN: mkString(``),
EDGE_APEX_DOMAIN: mkString(_APEX_DOMAIN), EDGE_APEX_DOMAIN: mkString(_APEX_DOMAIN),
EDGE_MAX_ACTIVE_INSTANCES: mkNumber(20), EDGE_MAX_ACTIVE_INSTANCES: mkNumber(20),
@ -232,6 +233,8 @@ export const PH_FTP_PASV_IP = () => settings().PH_FTP_PASV_IP
export const PH_FTP_PASV_PORT_MIN = () => settings().PH_FTP_PASV_PORT_MIN export const PH_FTP_PASV_PORT_MIN = () => settings().PH_FTP_PASV_PORT_MIN
export const PH_FTP_PASV_PORT_MAX = () => settings().PH_FTP_PASV_PORT_MAX export const PH_FTP_PASV_PORT_MAX = () => settings().PH_FTP_PASV_PORT_MAX
export const EDGE_SASS_DOMAINS_AUTH_TOKEN = () =>
settings().EDGE_SASS_DOMAINS_AUTH_TOKEN
export const EDGE_APEX_DOMAIN = () => settings().EDGE_APEX_DOMAIN export const EDGE_APEX_DOMAIN = () => settings().EDGE_APEX_DOMAIN
export const EDGE_MAX_ACTIVE_INSTANCES = () => export const EDGE_MAX_ACTIVE_INSTANCES = () =>
settings().EDGE_MAX_ACTIVE_INSTANCES settings().EDGE_MAX_ACTIVE_INSTANCES

View File

@ -5,6 +5,7 @@ import { default as Server, default as httpProxy } from 'http-proxy'
import { AsyncReturnType } from 'type-fest' import { AsyncReturnType } from 'type-fest'
import { import {
DAEMON_PORT, DAEMON_PORT,
EDGE_SASS_DOMAINS_AUTH_TOKEN,
Logger, Logger,
LoggerService, LoggerService,
SingletonBaseConfig, SingletonBaseConfig,
@ -49,22 +50,17 @@ export const proxyService = mkSingleton(async (config: ProxyServiceConfig) => {
res.end res.end
}) })
// Default locals
server.use((req, res, next) => { server.use((req, res, next) => {
const host = req.headers.host const host = req.headers.host
if (!host) {
throw new Error(`Host not found`)
}
res.locals.host = host res.locals.host = host
next()
})
server.use((req, res, next) => {
res.locals.coreInternalUrl = coreInternalUrl res.locals.coreInternalUrl = coreInternalUrl
next() next()
}) })
// Cloudflare signature
server.use((req, res, next) => { server.use((req, res, next) => {
const url = new URL(`http://${req.headers.host}${req.url}`) const url = new URL(`https://${res.locals.host}${req.url}`)
const country = (req.headers['cf-ipcountry'] as string) || '<ct>' const country = (req.headers['cf-ipcountry'] as string) || '<ct>'
const ip = (req.headers['x-forwarded-for'] as string) || '<ip>' const ip = (req.headers['x-forwarded-for'] as string) || '<ip>'
const method = req.method || '<m>' const method = req.method || '<m>'
@ -74,7 +70,36 @@ export const proxyService = mkSingleton(async (config: ProxyServiceConfig) => {
ip.padEnd(45), ip.padEnd(45),
url.toString(), url.toString(),
].join(' ') ].join(' ')
info(`Incoming request ${sig}`) res.locals.sig = sig
next()
})
// SaaS domains overrides
server.use((req, res, next) => {
if (!(`x-saas-domains-auth-token` in req.headers)) {
next()
return
}
const secret = EDGE_SASS_DOMAINS_AUTH_TOKEN()
if (req.headers[`x-saas-domains-auth-token`] !== secret) {
throw new Error(`Invalid SaaS domain secret`)
}
const host = req.headers[`x-served-for`]
res.locals.host = host
const url = new URL(`https://${host}${req.url}`)
const country =
(req.headers['x-saas-geoip-country-code'] as string) || '<ct>'
const ip = (req.headers['x-saas-domains-ip'] as string) || '<ip>'
const method = req.method || '<m>'
const sig = [
method.padStart(10),
country.padStart(5),
ip.padEnd(45),
url.toString(),
].join(' ')
res.locals.sig = sig res.locals.sig = sig
next() next()
}) })
@ -84,6 +109,19 @@ export const proxyService = mkSingleton(async (config: ProxyServiceConfig) => {
next() next()
}) })
// Request logging
server.use((req, res, next) => {
if (!res.locals.host) {
throw new Error(`Host not found`)
}
next()
})
server.use((req, res, next) => {
info(`Incoming request ${res.locals.sig}`, req.headers)
next()
})
server.listen(DAEMON_PORT(), () => { server.listen(DAEMON_PORT(), () => {
info(`daemon listening on port ${DAEMON_PORT()}`) info(`daemon listening on port ${DAEMON_PORT()}`)
}) })