Separate route definitions and where they're served from

This commit is contained in:
2025-03-07 10:28:17 -06:00
parent d6fccc3172
commit ad2b85bc2b
4 changed files with 138 additions and 53 deletions

45
deno/app.ts Normal file
View File

@@ -0,0 +1,45 @@
// app.ts
import { services } from "./services";
import{DenoRequest, Method, ProcessedRoute, Request, Route} from './types'
import {routes} from './routes'
services.logging.log({ foo: 1 });
const processedRoutes: ProcessedRoute[] = routes.map(
(route: Route, idx: number, allRoutes: Route[]) => {
const pattern: URLPattern = new URLPattern({ pathname: route.path });
const method: Method = route.method;
const handler = async (denoRequest: DenoRequest) => {
const req: Request = {
pattern: route.pattern,
path: denoRequest.path,
method: denoRequest.method,
parameters: { one: 1, two: 2 },
denoRequest,
};
return route.handler(req);
};
const retval: ProcessedRoute = { pattern, method, handler };
return retval
},
);
async function handler(req: globalThis.Request): globalThis.Response {
for (const [idx, pr] of processedRoutes.entries()) {
const match = pr.pattern.exec(req.url);
if (match) {
const resp = await pr.handler(req);
return new globalThis.Response(resp.result);
}
}
return new globalThis.Response("not found", { status: 404 });
}
Deno.serve(handler);

View File

@@ -1,18 +1,16 @@
type Method = "get" | "post" | "put" | "patch" | "delete"; /// <reference lib="dom" />
import { sleep } from "https://deno.land/x/sleep/mod.ts";
import { HttpCode, httpCodes } from "./http-codes.ts"; import { HttpCode, httpCodes } from "./http-codes.ts";
import { ContentType, contentTypes } from "./content-types"; import { ContentType, contentTypes } from "./content-types";
import { services } from "./services"; import { services } from "./services";
import {DenoRequest, Handler, Response, Method, UserRequest, Request, Route, ProcessedRoute } from './types.ts'
type Response = {
code: HttpCode;
contentType: ContentType;
result: string;
};
type Handler = (req: Request) => Response;
const phandler: Handler = (req: Request) => {
const phandler: Handler = async (req: Request) => {
const code = httpCodes.success.OK; const code = httpCodes.success.OK;
return { return {
code, code,
@@ -21,17 +19,54 @@ const phandler: Handler = (req: Request) => {
}; };
}; };
type Route = {
path: string;
methods: Method[]; // FIXME: Obviously put this somewhere else
handler: Handler; const okText = (out: string) => {
const code = httpCodes.success.OK;
return {
code,
result: out,
contentType: contentTypes.text.plain,
};
}; };
const routes: Route[] = [ const routes: Route[] = [
{
path: "/slow",
methods: ["get"],
handler: async (_req) => {
console.log("starting slow request") ;
await sleep(10);
console.log("finishing slow request"); return okText("that was slow");
},
},
{
path: "/list",
methods: ["get"],
handler: async (_req) => {
const code = httpCodes.success.OK;
const lr = (rr: Route[]) => {
const ret = rr.map((r: Route) => {
return r.path;
});
return ret;
};
const listing = lr(routes).join(", ");
return {
code,
result: listing + "\n",
contentType: contentTypes.text.plain,
};
},
},
{ {
path: "/ok", path: "/ok",
methods: ["get"], methods: ["get"],
handler: (req) => { handler: async (_req) => {
const code = httpCodes.success.OK; const code = httpCodes.success.OK;
const rn = services.random.randomNumber(); const rn = services.random.randomNumber();
@@ -45,7 +80,7 @@ const routes: Route[] = [
{ {
path: "/alsook", path: "/alsook",
methods: ["get"], methods: ["get"],
handler: (req) => { handler: async (_req) => {
const code = httpCodes.success.OK; const code = httpCodes.success.OK;
return { return {
code, code,
@@ -56,46 +91,11 @@ const routes: Route[] = [
}, },
]; ];
type DenoRequest = globalThis.Request;
type UserRequest = {};
type Request = {
pattern: string;
path: string;
method: Method;
parameters: object;
denoRequest: globalThis.Request;
};
type ProcessedRoute = { pattern: URLPattern; method: Method; handler: Handler };
const processedRoutes: ProcessedRoute[] = routes.map(
(route: Route, idx: number, allRoutes: Route[]) => {
const pattern: URLPattern = new URLPattern({ pathname: route.path });
const method: Method = route.method;
const handler = (denoRequest: DenoRequest) => {
const req: Request = {
pattern: route.pattern,
path: denoRequest.path,
method: denoRequest.method,
parameters: { one: 1, two: 2 },
denoRequest,
};
return route.handler(req);
};
return { pattern, method, handler };
},
);
function handler(req: globalThis.Request): globalThis.Response {
for (const [idx, pr] of processedRoutes.entries()) {
const match = pr.pattern.exec(req.url);
if (match) {
const resp = pr.handler(req);
return new globalThis.Response(resp.result);
}
}
return new globalThis.Response("not found", { status: 404 });
}
Deno.serve(handler);
export {routes}

View File

@@ -6,6 +6,6 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd "$DIR" cd "$DIR"
deno run --allow-net --unstable-sloppy-imports --watch routes.ts deno run --allow-net --unstable-sloppy-imports --watch app.ts

40
deno/types.ts Normal file
View File

@@ -0,0 +1,40 @@
// types.ts
// FIXME: split this up into types used by app developers and types internal
// to the framework.
import { HttpCode, httpCodes } from "./http-codes.ts";
import { ContentType, contentTypes } from "./content-types";
export type Method = "get" | "post" | "put" | "patch" | "delete";
export type DenoRequest = globalThis.Request;
export type UserRequest = {};
export type Request = {
pattern: string;
path: string;
method: Method;
parameters: object;
denoRequest: globalThis.Request;
};
export type ProcessedRoute = { pattern: URLPattern; method: Method; handler: Handler };
export type Response = {
code: HttpCode;
contentType: ContentType;
result: string;
};
export type Handler = (req: Request) => Promise<Response>;
export type Route = {
path: string;
methods: Method[];
handler: Handler;
interruptable?: boolean
};