76 lines
2.2 KiB
TypeScript
76 lines
2.2 KiB
TypeScript
import { AlpineApp } from "@dx/alpine-server";
|
|
import { Context, Router } from "@oak/oak";
|
|
|
|
let config = {
|
|
api_url: Deno.env.get("API_URL") || "http://localhost:8080",
|
|
port: parseInt(Deno.env.get("PORT") || "8090"),
|
|
};
|
|
|
|
try {
|
|
const configFile = await Deno.readTextFile("./config.json");
|
|
const fileConfig = JSON.parse(configFile);
|
|
config = { ...config, ...fileConfig };
|
|
// deno-lint-ignore no-explicit-any
|
|
} catch (e: any) {
|
|
console.warn("Could not read config.json, using defaults", e.message);
|
|
}
|
|
|
|
const app = new AlpineApp({
|
|
app: {
|
|
dev: true,
|
|
staticFilesPath: "./public",
|
|
},
|
|
oak: {
|
|
listenOptions: { port: config.port },
|
|
},
|
|
});
|
|
|
|
const healthRouter = new Router();
|
|
healthRouter.get("/health", (ctx: Context) => {
|
|
ctx.response.body = { status: "ok" };
|
|
ctx.response.status = 200;
|
|
});
|
|
app.append(healthRouter);
|
|
|
|
app.use(async (ctx: Context, next: () => Promise<unknown>) => {
|
|
await next();
|
|
const contentType = ctx.response.headers.get("content-type") || "";
|
|
if (contentType.includes("text/html")) {
|
|
let csp = ctx.response.headers.get("Content-Security-Policy");
|
|
if (!csp) {
|
|
// securityHeaders might not have set it yet if it runs after us in the call stack
|
|
// but in run(), securityHeaders is app.use()ed BEFORE user middlewares.
|
|
// So when we are here (after await next()), securityHeaders has already finished its await next()
|
|
// and set the headers.
|
|
csp = [
|
|
"default-src 'self'",
|
|
"base-uri 'self'",
|
|
"object-src 'none'",
|
|
"frame-ancestors 'none'",
|
|
"script-src 'self' 'unsafe-eval'",
|
|
"style-src 'self'",
|
|
"img-src 'self' data:",
|
|
"font-src 'self'",
|
|
"connect-src 'self'",
|
|
"media-src 'self'",
|
|
].join("; ");
|
|
}
|
|
const updatedCsp = csp.replace(
|
|
"connect-src 'self'",
|
|
`connect-src 'self' ${config.api_url} ws:`,
|
|
);
|
|
ctx.response.headers.set("Content-Security-Policy", updatedCsp);
|
|
}
|
|
});
|
|
|
|
console.log(`URL: http://localhost:${config.port}`);
|
|
console.log(`API: ${config.api_url}`);
|
|
|
|
// Create config.js file in public directory
|
|
await Deno.writeTextFile(
|
|
"./public/config.js",
|
|
`window.APP_CONFIG = ${JSON.stringify(config)};`,
|
|
);
|
|
|
|
await app.run();
|