diff --git a/env.dist b/env.dist index 7ce1b83..c2e5f5f 100644 --- a/env.dist +++ b/env.dist @@ -14,4 +14,5 @@ DATABASE_URL=./water_stations.db # Server configuration PORT=3000 +# Set to true to force HTTPS redirects (works with reverse proxies) FORCE_HTTPS=false \ No newline at end of file diff --git a/server.js b/server.js index 63516aa..1fc7e77 100644 --- a/server.js +++ b/server.js @@ -92,14 +92,24 @@ app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); app.use(express.static(path.join(__dirname, 'public'))); +// Trust proxy headers (required for Apache/nginx reverse proxy setups) +app.set('trust proxy', true); + // HTTPS enforcement middleware if (FORCE_HTTPS) { app.use((req, res, next) => { - if (req.header('x-forwarded-proto') !== 'https') { - res.redirect(`https://${req.header('host')}${req.url}`); - } else { - next(); + // Check if the original request was HTTP + // req.secure will be true if the original request was HTTPS (when trust proxy is enabled) + // x-forwarded-proto header is set by the proxy + const isHttps = req.secure || req.header('x-forwarded-proto') === 'https'; + + if (!isHttps) { + // Only redirect if the original client request was HTTP + const host = req.header('x-forwarded-host') || req.header('host'); + return res.redirect(301, `https://${host}${req.url}`); } + + next(); }); } @@ -122,8 +132,13 @@ app.use(passport.session()); // Helper function to get base URL function getBaseUrl(req) { - const protocol = FORCE_HTTPS || req.secure || req.header('x-forwarded-proto') === 'https' ? 'https' : 'http'; - const host = req.header('host'); + // Determine protocol: use HTTPS if forced, or if original request was HTTPS + const isHttps = FORCE_HTTPS || req.secure || req.header('x-forwarded-proto') === 'https'; + const protocol = isHttps ? 'https' : 'http'; + + // Use x-forwarded-host if available (set by proxy), otherwise use host header + const host = req.header('x-forwarded-host') || req.header('host'); + return `${protocol}://${host}`; }