Minimale git-remote met publiek/prive-toggle
Deze repository wordt als momentopname gepubliceerd: een clone bevat de volledige inhoud, maar geen commitgeschiedenis.
import fs from "node:fs/promises";
import path from "node:path";
import { fileURLToPath } from "node:url";
import express from "express";
import { identify } from "./auth.ts";
import { config } from "./config.ts";
import { publishSnapshot } from "./git.ts";
import { listRepos } from "./repos.ts";
import { adminRouter } from "./routes/admin.ts";
import { gitHttpHandler } from "./routes/smart-http.ts";
import { repoBrowser, repoIndex, sendError } from "./routes/web.ts";
const here = path.dirname(fileURLToPath(import.meta.url));
const publicDir = path.resolve(here, "..", "public");
const app = express();
app.disable("x-powered-by");
if (config.trustProxy) app.set("trust proxy", true);
app.use((_req, res, next) => {
res.setHeader(
"Content-Security-Policy",
"default-src 'self'; script-src 'none'; style-src 'self'; img-src 'self' data: https:; frame-ancestors 'none'; base-uri 'none'; form-action 'self'",
);
res.setHeader("X-Content-Type-Options", "nosniff");
res.setHeader("Referrer-Policy", "same-origin");
next();
});
app.use(identify);
// Het git-transport moet de ruwe request-body kunnen streamen, dus dit staat
// bewust vóór express.urlencoded — die zou de stream anders al opgeslurpt hebben.
app.use(config.gitPrefix, gitHttpHandler(false));
app.use(config.gitFullPrefix, gitHttpHandler(true));
app.use("/assets", express.static(publicDir, { maxAge: "1h", index: false }));
app.use(express.urlencoded({ extended: false, limit: "64kb" }));
app.use(adminRouter);
app.get("/", repoIndex);
app.use("/r", repoBrowser);
app.use((req, res) => {
sendError(req, res, 404, "Deze pagina bestaat niet.");
});
app.use(
(
error: Error,
req: express.Request,
res: express.Response,
_next: express.NextFunction,
): void => {
console.error(error);
if (res.headersSent) {
res.end();
return;
}
sendError(req, res, 500, "Er ging iets mis op de server.");
},
);
await fs.mkdir(config.repoRoot, { recursive: true });
// Zorgt dat elke repository een publieke momentopname heeft, ook eentje die er al
// stond voordat dit bestond. Ongewijzigde inhoud levert geen nieuwe commit op.
for (const repo of await listRepos()) {
try {
await publishSnapshot(repo.dir, repo.publishedDir);
} catch (error) {
console.error(`[publish] ${repo.name}: momentopname bijwerken mislukt`, error);
}
}
app.listen(config.port, config.host, () => {
console.log(`pub-repo luistert op http://${config.host}:${config.port}`);
console.log(`repositories in ${config.repoRoot}`);
console.log(`clone-URL's: ${config.publicUrl}${config.gitPrefix}/<naam>.git`);
});