mirror of
https://github.com/ragestudio/comty.git
synced 2025-06-09 02:24:16 +00:00
Add support for extra proxies via external file
Allows defining custom reverse proxy routes via an `extra-proxies.js` file at the project root. The Gateway loads these configurations on startup. Additionally, the Nginx gateway manager no longer applies default prefix-stripping rewrites. Explicit `pathRewrite` rules are now required if prefix stripping is needed for any proxied service, including those defined externally.
This commit is contained in:
parent
80d84b3e17
commit
1b6d1c74a1
7
packages/server/extra-proxies.js
Normal file
7
packages/server/extra-proxies.js
Normal file
@ -0,0 +1,7 @@
|
||||
export default {
|
||||
"/spectrum/*": {
|
||||
target: process.env.SPECTRUM_API ?? "https://live.ragestudio.net",
|
||||
pathRewrite: { "^/spectrum/(.*)": "/$1", "^/spectrum": "/" },
|
||||
websocket: true,
|
||||
},
|
||||
}
|
@ -165,6 +165,92 @@ export default class Gateway {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads and registers additional proxy routes from ../../extra-proxies.js
|
||||
*/
|
||||
async registerExtraProxies() {
|
||||
try {
|
||||
// Dynamic import is relative to the current file.
|
||||
// extra-proxies.js can be CJS (module.exports = ...) or ESM (export default ...)
|
||||
const extraProxiesModule = require(
|
||||
path.resolve(process.cwd(), "extra-proxies.js"),
|
||||
)
|
||||
const extraProxies = extraProxiesModule.default // Node's CJS/ESM interop puts module.exports on .default
|
||||
|
||||
if (
|
||||
!extraProxies ||
|
||||
typeof extraProxies !== "object" ||
|
||||
Object.keys(extraProxies).length === 0
|
||||
) {
|
||||
console.log(
|
||||
"[Gateway] No extra proxies defined in `extra-proxies.js`, file is empty, or format is invalid. Skipping.",
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
console.log(
|
||||
`[Gateway] Registering extra proxies from 'extra-proxies.js'...`,
|
||||
)
|
||||
|
||||
for (const proxyPathKey in extraProxies) {
|
||||
if (
|
||||
Object.prototype.hasOwnProperty.call(
|
||||
extraProxies,
|
||||
proxyPathKey,
|
||||
)
|
||||
) {
|
||||
const config = extraProxies[proxyPathKey]
|
||||
if (!config || typeof config.target !== "string") {
|
||||
console.warn(
|
||||
`[Gateway] Skipping invalid extra proxy config for path: '${proxyPathKey}' in 'extra-proxies.js'. Target is missing or not a string.`,
|
||||
)
|
||||
continue
|
||||
}
|
||||
|
||||
let registrationPath = proxyPathKey
|
||||
|
||||
// Normalize paths ending with /*
|
||||
// e.g., "/spectrum/*" becomes "/spectrum"
|
||||
// e.g., "/*" becomes "/"
|
||||
if (registrationPath.endsWith("/*")) {
|
||||
registrationPath = registrationPath.slice(0, -2)
|
||||
if (registrationPath === "") {
|
||||
registrationPath = "/"
|
||||
}
|
||||
}
|
||||
|
||||
console.log(
|
||||
`[Gateway] Registering extra proxy: '${proxyPathKey}' (as '${registrationPath}') -> ${config.target}`,
|
||||
)
|
||||
|
||||
await this.gateway.register({
|
||||
serviceId: `extra-proxy:${registrationPath}`, // Unique ID for this proxy rule
|
||||
path: registrationPath,
|
||||
target: config.target,
|
||||
pathRewrite: config.pathRewrite, // undefined if not present
|
||||
websocket: !!config.websocket, // false if not present or falsy
|
||||
})
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
// Handle cases where the extra-proxies.js file might not exist
|
||||
if (
|
||||
error.code === "ERR_MODULE_NOT_FOUND" ||
|
||||
(error.message &&
|
||||
error.message.toLowerCase().includes("cannot find module"))
|
||||
) {
|
||||
console.log(
|
||||
"[Gateway] `extra-proxies.js` not found. Skipping extra proxy registration.",
|
||||
)
|
||||
} else {
|
||||
console.error(
|
||||
"[Gateway] Error loading or registering extra proxies from `extra-proxies.js`:",
|
||||
error,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle both router and websocket registration requests from services
|
||||
* @param {Service} service - Service registering a route or websocket
|
||||
@ -304,6 +390,9 @@ export default class Gateway {
|
||||
await this.gateway.initialize()
|
||||
}
|
||||
|
||||
// Register any externally defined proxies before services start
|
||||
await this.registerExtraProxies()
|
||||
|
||||
// Watch for service state changes
|
||||
Observable.observe(this.serviceRegistry, (changes) => {
|
||||
this.checkAllServicesReady()
|
||||
|
@ -371,19 +371,12 @@ http {
|
||||
|
||||
if (route.pathRewrite && Object.keys(route.pathRewrite).length > 0) {
|
||||
rewriteConfig += "# Path rewrite rules\n"
|
||||
|
||||
for (const [pattern, replacement] of Object.entries(
|
||||
route.pathRewrite,
|
||||
)) {
|
||||
// Improved rewrite pattern that preserves query parameters
|
||||
rewriteConfig += `\trewrite ${pattern} ${replacement}$is_args$args break;`
|
||||
}
|
||||
} else {
|
||||
// If no explicit rewrite is defined, but we need to strip the path prefix,
|
||||
// Generate a default rewrite that preserves the URL structure
|
||||
if (path !== "/") {
|
||||
rewriteConfig += "# Default path rewrite to strip prefix\n"
|
||||
rewriteConfig += `\trewrite ^${path}(/.*)$ $1$is_args$args break;\n`
|
||||
rewriteConfig += `\trewrite ^${path}$ / break;`
|
||||
rewriteConfig += `\nrewrite ${pattern} ${replacement} break;`
|
||||
}
|
||||
}
|
||||
|
||||
@ -423,6 +416,8 @@ ${locationDirective} {
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
|
||||
${rewriteConfig}
|
||||
|
||||
# Proxy pass to service
|
||||
proxy_pass ${route.target};
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user