diff --git a/config.json b/config.json index 7357926..eeaf19c 100644 --- a/config.json +++ b/config.json @@ -23,7 +23,7 @@ "app": { "urlClient": "https://dev.tombutcher.work", "urlElectronClient": "http://localhost:5780", - "urlApi": "https://dev.tombutcher.work/api", + "urlApi": "https://dev.tombutcher.work/fcapi", "devAuthClient": "http://localhost:3500", "jenkinsProject": "https://ci.tombutcher.work/job/farmcontrol/job/farmcontrol-ui", "appUpdateStorage": "https://dist.farmcontrol.app/jenkins/farmcontrol/farmcontrol-ui" diff --git a/src/index.js b/src/index.js index 422419a..936bdf4 100644 --- a/src/index.js +++ b/src/index.js @@ -91,6 +91,22 @@ const app = express(); const logger = log4js.getLogger('App'); logger.level = config.server.logLevel; +// Public path prefix from app.urlApi (e.g. https://host/fcapi -> /fcapi). +// Empty when the API is served at the host root. Requests that still carry +// the prefix (reverse proxy did not strip it) are rewritten before routing. +function apiPathPrefix() { + const urlApi = config.app?.urlApi; + if (!urlApi) return ''; + try { + const pathname = new URL(urlApi).pathname.replace(/\/+$/, ''); + return pathname && pathname !== '/' ? pathname : ''; + } catch { + return ''; + } +} + +const API_PREFIX = apiPathPrefix(); + app.use(log4js.connectLogger(logger, { level: 'trace' })); const allowedOrigins = [ @@ -119,6 +135,7 @@ async function initializeApp() { logger.info(`Environment: ${getEnvironment()}`); logger.info(`Port: ${PORT}`); logger.info(`Log Level: ${config.server.logLevel}`); + logger.info(`API path prefix: ${API_PREFIX || '(none)'}`); try { // Connect to database await dbConnect(); @@ -174,6 +191,21 @@ app.use( app.use(express.json()); app.use(populateUserMiddleware); +if (API_PREFIX) { + app.use((req, _res, next) => { + const url = req.url || '/'; + const matches = + url === API_PREFIX || + url.startsWith(`${API_PREFIX}/`) || + url.startsWith(`${API_PREFIX}?`); + if (matches) { + const stripped = url.slice(API_PREFIX.length); + req.url = stripped === '' ? '/' : stripped; + } + next(); + }); +} + app.get('/', function (req, res) { const __dirname = fs.realpathSync('.'); res.sendFile(path.join(__dirname, '/src/landing/index.html'));