Files
deno-no-ipv4-here/app.ts
2025-07-30 13:36:00 +02:00

76 lines
1.9 KiB
TypeScript

import { Application, Router, type Context, type Next } from "jsr:@oak/oak";
import { join } from "jsr:@std/path";
import { Eta } from "jsr:@eta-dev/eta";
// Create Eta instance
const eta = new Eta({
views: join(Deno.cwd(), "views"),
cache: Deno.env.get("SERVICE_DOMAIN") === "production",
});
// Create Oak application
const app = new Application();
const router = new Router();
// Serve static files
app.use(async (ctx: Context, next: Next) => {
const staticPath = join(Deno.cwd(), "static");
try {
// Strip /static prefix from path
const path = ctx.request.url.pathname.replace(/^\/static/, '');
await ctx.send({
root: staticPath,
path: path,
index: "index.html",
});
} catch {
await next();
}
});
// Main route handler
router.get("/", async (ctx: Context) => {
const params = ctx.request.url.searchParams;
let back_to_url = params.get("back_to") || "";
let domain = "";
// If no back_to parameter, check host header
if (!back_to_url) {
const host = ctx.request.headers.get("host") || "";
const serviceDomain = Deno.env.get("SERVICE_DOMAIN") || "localhost";
const domainRegex = new RegExp(`^(${serviceDomain.replace(/\./g, '\\.')}|localhost)`);
// Exclude our own hosts
if (host && !domainRegex.test(host)) {
back_to_url = `http://${host}`;
}
}
// Extract domain from URL
if (back_to_url) {
try {
domain = new URL(back_to_url).hostname;
} catch {
// Invalid URL, ignore
}
}
// Render template with context
const html = await eta.render("index", {
back_to_url,
domain: domain || "This part of the Internet",
});
ctx.response.body = html;
ctx.response.type = "text/html";
});
app.use(router.routes());
app.use(router.allowedMethods());
// Start server
const port = 8080;
console.log(`Server running on http://localhost:${port}`);
await app.listen({ port });