From ecdbedc1350a8a0e9f81f75b0eb3885aafacd9cd Mon Sep 17 00:00:00 2001 From: Michael Wolf Date: Fri, 7 Mar 2025 21:22:31 -0600 Subject: [PATCH] Clean up how route handlers are called --- deno/app.ts | 60 ++++++++++++++++++++++++++++++++++++++---------- deno/routes.ts | 18 +++++++-------- deno/services.ts | 1 - deno/types.ts | 12 ++++++---- 4 files changed, 64 insertions(+), 27 deletions(-) diff --git a/deno/app.ts b/deno/app.ts index 7ec9e1b..d251eab 100644 --- a/deno/app.ts +++ b/deno/app.ts @@ -1,39 +1,75 @@ import { services } from "./services.ts"; import { DenoRequest, - massageMethod,DenoResponse, + DenoResponse, + InternalHandler, + massageMethod, Method, ProcessedRoute, - Request, + Request as Request, Route, } from "./types.ts"; import { routes } from "./routes.ts"; services.logging.log({ source: "logging", text: ["1"] }); -const processedRoutes: ProcessedRoute[] = routes.map( +const processedRoutes: { [K in Method]: ProcessedRoute[] } = { + "GET": [], + "POST": [], + "PUT": [], + "PATCH": [], + "DELETE": [], +}; + +function isPromise(value: T | Promise): value is Promise { + return typeof (value as any)?.then === "function"; +} + +routes.forEach( (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 methodList = route.methods; + + const handler: InternalHandler = async (denoRequest: DenoRequest) => { + const method = massageMethod(denoRequest.method); + + if (!methodList.includes(method)) { + // XXX: Worth asserting this? + } + + const p = new URL(denoRequest.url); + const path = p.pathname; + const req: Request = { - pattern: route.pattern, - path: denoRequest.path, - method: massageMethod(denoRequest.method), + pattern: route.path, + path, + method, parameters: { one: 1, two: 2 }, denoRequest, }; - return route.handler(req); + + const retval = route.handler(req); + if (isPromise(retval)) { + return await retval; + } else { + return retval; + } }; - const retval: ProcessedRoute = { pattern, method, handler }; + for (const [_idx, method] of methodList.entries()) { + const pr: ProcessedRoute = { pattern, method, handler }; - return retval; + processedRoutes[method].push(pr); + } }, ); async function handler(req: DenoRequest): Promise { - for (const [idx, pr] of processedRoutes.entries()) { + const m = req.method; + const m1 = massageMethod(m); + + const byMethod = processedRoutes[m1]; + for (const [_idx, pr] of byMethod.entries()) { const match = pr.pattern.exec(req.url); if (match) { const resp = await pr.handler(req); diff --git a/deno/routes.ts b/deno/routes.ts index b5b10d0..85f0f48 100644 --- a/deno/routes.ts +++ b/deno/routes.ts @@ -30,18 +30,18 @@ const okText = (out: string) => { const routes: Route[] = [ { path: "/slow", - methods: ["get"], - handler: async (_req) => { + methods: ["GET"], + handler: async (_req: Request) => { console.log("starting slow request"); - await sleep(10); + await sleep(2); console.log("finishing slow request"); return okText("that was slow"); }, }, { path: "/list", - methods: ["get"], - handler: async (_req) => { + methods: ["GET"], + handler: (_req: Request) => { const code = httpCodes.success.OK; const lr = (rr: Route[]) => { const ret = rr.map((r: Route) => { @@ -61,8 +61,8 @@ const routes: Route[] = [ }, { path: "/ok", - methods: ["get"], - handler: async (_req) => { + methods: ["GET"], + handler: (_req: Request) => { const code = httpCodes.success.OK; const rn = services.random.randomNumber(); @@ -75,8 +75,8 @@ const routes: Route[] = [ }, { path: "/alsook", - methods: ["get"], - handler: async (_req) => { + methods: ["GET"], + handler: (_req) => { const code = httpCodes.success.OK; return { code, diff --git a/deno/services.ts b/deno/services.ts index cbbc4a6..94a476d 100644 --- a/deno/services.ts +++ b/deno/services.ts @@ -4,7 +4,6 @@ import { randomNumber } from "https://deno.land/x/random_number/mod.ts"; import { config } from "./config.ts"; import { getLogs, log } from "./logging.ts"; - //const database = Client({ //}) diff --git a/deno/types.ts b/deno/types.ts index 2768484..767d03a 100644 --- a/deno/types.ts +++ b/deno/types.ts @@ -18,13 +18,13 @@ const methodParser = z.union([ export type Method = z.infer; const massageMethod = (input: string): Method => { - const r = methodParser.parse(input.toUpperCase()) + const r = methodParser.parse(input.toUpperCase()); return r; }; export type DenoRequest = globalThis.Request; -export type DenoResponse=globalThis.Response; +export type DenoResponse = globalThis.Response; export type UserRequest = {}; export type Request = { pattern: string; @@ -33,10 +33,14 @@ export type Request = { parameters: object; denoRequest: globalThis.Request; }; + +export type InternalHandler = (req: DenoRequest) => Promise; + +export type Handler = (req: Request) => Promise | Response; export type ProcessedRoute = { pattern: URLPattern; method: Method; - handler: Handler; + handler: InternalHandler; }; export type Response = { @@ -45,8 +49,6 @@ export type Response = { result: string; }; -export type Handler = (req: Request) => Promise; - export type Route = { path: string; methods: Method[];