-
-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #30 from jordan-dalby/21-subpath-fix
Simplified server
- Loading branch information
Showing
4 changed files
with
73 additions
and
46 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,56 +1,80 @@ | ||
const express = require('express'); | ||
const bodyParser = require('body-parser'); | ||
const path = require('path'); | ||
const fs = require('fs'); | ||
const { initializeDatabase } = require('./config/database'); | ||
const snippetRoutes = require('./routes/snippetRoutes'); | ||
const authRoutes = require('./routes/authRoutes'); | ||
const { authenticateToken } = require('./middleware/auth'); | ||
const { join } = require('path'); | ||
const fs = require('fs'); | ||
|
||
const expressApp = express(); | ||
const port = 5000; | ||
const app = express(); | ||
const PORT = 5000; | ||
|
||
function app(server) { | ||
server.use(bodyParser.json()); | ||
server.set('trust proxy', true); | ||
app.use(express.json()); | ||
|
||
const clientBuildPath = '/client/build'; | ||
const basePath = process.env.BASE_PATH || ''; | ||
const buildPath = join(__dirname, '../../client/build'); | ||
const assetsPath = join(buildPath, 'assets'); | ||
|
||
server.use(express.static(clientBuildPath)); | ||
server.use('/api/auth', authRoutes); | ||
server.use('/api/snippets', authenticateToken, snippetRoutes); | ||
|
||
server.get('*', (req, res) => { | ||
if (req.path.includes('/assets/') || req.path.endsWith('.json')) { | ||
console.log('404 for static file:', req.path); | ||
res.status(404).send('File not found'); | ||
} else { | ||
res.sendFile(path.join(clientBuildPath, 'index.html')); | ||
} | ||
}); | ||
} | ||
|
||
async function startServer() { | ||
try { | ||
await initializeDatabase(); | ||
return new Promise((resolve) => { | ||
expressApp.listen(port, () => { | ||
console.log(`Server running on port ${port}`); | ||
resolve(); | ||
}); | ||
}); | ||
} catch (error) { | ||
console.error('Failed to initialize database:', error); | ||
throw error; | ||
app.use(`${basePath}/api/auth`, authRoutes); | ||
app.use(`${basePath}/api/snippets`, authenticateToken, snippetRoutes); | ||
|
||
app.use(`${basePath}/assets`, express.static(assetsPath)); | ||
app.use(`${basePath}/monacoeditorwork`, express.static(join(buildPath, 'monacoeditorwork'))); | ||
|
||
app.use(basePath, express.static(buildPath, { index: false })); | ||
|
||
/* | ||
* A bit of a hack, we need to manually rewrite the HTML to support base paths with ingress | ||
* If given a base path of /bytestash, the index.html file will still be using /assets/xyz.css | ||
* But of course the files are not there on ingress, so we need to change them to /bytestash/assets/xyz.css | ||
* It's a bit of a hacky mess but this is the only solution I figured out without directly modifying vite.config.ts | ||
* on the client, but this will affect everyone, so not a viable solution | ||
* | ||
* We're also injecting the base path into the HTML so that the client can know the value without relying on an | ||
* environment variable, which would be baked into the client code at build time, which is not acceptable in this case | ||
*/ | ||
app.get(`${basePath}/*`, (req, res, next) => { | ||
if (req.url.startsWith(`${basePath}/api`)) { | ||
return next(); | ||
} | ||
|
||
// Don't cache, if the base path changes the previous index.html file is still used which will have incorrect paths | ||
res.set({ | ||
'Cache-Control': 'no-store, no-cache, must-revalidate, proxy-revalidate', | ||
'Pragma': 'no-cache', | ||
'Expires': '0', | ||
}); | ||
|
||
fs.readFile(join(buildPath, 'index.html'), 'utf8', (err, data) => { | ||
if (err) { | ||
return res.status(500).send('Error loading index.html'); | ||
} | ||
} | ||
|
||
const modifiedHtml = data.replace( | ||
/(src|href)="\/assets\//g, | ||
`$1="${basePath}/assets/` | ||
).replace( | ||
/\/monacoeditorwork\//g, | ||
`${basePath}/monacoeditorwork/` | ||
); | ||
|
||
if (require.main === module) { | ||
app(expressApp); | ||
startServer().catch(err => { | ||
console.error('Failed to start server:', err); | ||
process.exit(1); | ||
}); | ||
} | ||
const scriptInjection = `<script>window.__BASE_PATH__ = "${basePath}";</script>`; | ||
const injectedHtml = modifiedHtml.replace( | ||
'</head>', | ||
`${scriptInjection}</head>` | ||
); | ||
|
||
res.send(injectedHtml); | ||
}); | ||
}); | ||
|
||
(async () => { | ||
await initializeDatabase(); | ||
|
||
module.exports = { app, startServer }; | ||
return new Promise((resolve) => { | ||
app.listen(PORT, () => { | ||
console.log(`Server running on port ${PORT}`); | ||
resolve(); | ||
}); | ||
}); | ||
})(); |