Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# This is a fairly-standard multi-stage Dockerfile. We build
# This is a fairly-standard multi-stage Dockerfile. We build
# backend in a Node image, and then we copy the built files
# (but not the devDependencies [like typescript, etc.] or the raw source
# files) to final images that we'll actually run. This makes the final image a
Expand All @@ -18,6 +18,13 @@ COPY ["server", "./"]
FROM server_base AS build_backend
RUN npm run build

FROM node:24.14.1-bullseye-slim AS build_client
WORKDIR /app
COPY ["client/package.json", "client/package-lock.json", "./"]
RUN npm ci
COPY ["client", "./"]
RUN npm run build

# make a shared layer that can be the base for worker and api images.
FROM node:24.14.1-bullseye-slim AS backend_base
WORKDIR /app
Expand All @@ -39,6 +46,7 @@ ENV BUILD_ID=$BUILD_ID
# Expose 8080 because the backend will run on this port absent a
# process.env.PORT to the contrary.
FROM backend_base AS build_server
COPY --from=build_client /app/build ./client-build
EXPOSE 8080
CMD ["node", "bin/www.js"]

Expand Down
14 changes: 14 additions & 0 deletions server/server.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import path from 'path';
import { fileURLToPath } from 'url';
import express from 'express';

import makeApiApp from './api.js';
Expand Down Expand Up @@ -50,5 +52,17 @@

app.use('/api/v1', apiApp);

const clientBuildPath = path.resolve(
path.dirname(fileURLToPath(import.meta.url)),
'client-build',
);
app.use(express.static(clientBuildPath));
app.get('{*path}', (_req, res, next) => {
const indexPath = path.join(clientBuildPath, 'index.html');
res.sendFile(indexPath, (err) => {
if (err) next();
});
});

Check failure

Code scanning / CodeQL

Missing rate limiting High

This route handler performs
a file system access
, but is not rate-limited.
Comment on lines +60 to +65

return { app, shutdown };
}
Loading