Skip to content

Instantly share code, notes, and snippets.

@henriquegogo
Last active July 29, 2025 21:46
Show Gist options
  • Save henriquegogo/380ef79cfbcbcd636bfbddacd8e84584 to your computer and use it in GitHub Desktop.
Save henriquegogo/380ef79cfbcbcd636bfbddacd8e84584 to your computer and use it in GitHub Desktop.
Compact format of "request and render to..."
<dialog onclick="this.close()">
<iframe name="modal" onload="this.contentDocument.body.innerHTML.trim() ? (
this.style.height = 0, this.parentElement.showModal(),
this.style.height = this.contentDocument.body.scrollHeight + 'px'
) : this.parentElement.close()"></iframe>
</dialog>
async function handle(ev) {
ev.preventDefault();
const el = ev.currentTarget;
const { target, action, href = action, method = el._method?.value } = el;
const formData = new FormData(el.nodeName === "FORM" ? el : undefined);
if (!href) return document.querySelector(target).innerHTML = "";
const hasBody = method && method.toLowerCase() !== "get";
const url = hasBody ? href : `${href}?${new URLSearchParams(formData)}`;
const res = await fetch(url, hasBody ? { method, body: formData } : {});
document.querySelector(target).innerHTML = await res.text();
}
export class App {
constructor() {
this.routes = [];
this.middlewares = [];
["GET", "POST", "PUT", "PATCH", "DELETE"].forEach(method =>
this[method.toLowerCase()] = (path, handler) => this.add(method, path, handler)
);
}
use(fn) { this.middlewares.push(fn); }
add(method, path, handler) {
const keys = [];
const regex = new RegExp('^' + path
.replace(/:([^/]+)/g, (_, k) => { keys.push(k); return '([^/]+)'; })
.replace(/\*/g, '.*') + '$');
this.routes.push({ method, regex, keys, handler });
}
async fetch(req) {
const url = new URL(req.url);
req.query = url.searchParams;
req.path = url.pathname;
req.params = {};
const res = {
headers: new Headers(),
send(body, status = 200, type = "text/plain") {
return new Response(body, { status, headers: {
"Content-Type": type, ...Object.fromEntries(this.headers.entries())
}})
},
render(body, status) { return this.send(body, status, "text/html"); },
json(body, status) { return this.send(JSON.stringify(body), status, "application/json"); },
redirect(location, status = 302) {
this.headers.set("Location", location);
return this.send("", status, "text/plain");
}
};
for (const middleware of this.middlewares) {
const ret = await middleware(req, res);
if (ret instanceof Response) return ret;
}
for (const route of this.routes) {
if (route.method !== req.method) continue;
const method = req.path.match(route.regex);
if (method) {
route.keys.forEach((k, i) => req.params[k] = decodeURIComponent(method[i + 1]));
return await route.handler(req, res);
}
}
return res.send("Not Found", 404);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment