Get base files closer to being bootstrappable
This commit is contained in:
93
backend/diachron/routing.ts
Normal file
93
backend/diachron/routing.ts
Normal file
@@ -0,0 +1,93 @@
|
||||
import { contentTypes } from "./content-types";
|
||||
import { httpCodes } from "./http-codes";
|
||||
import express, {
|
||||
type NextFunction,
|
||||
type Request as ExpressRequest,
|
||||
type Response as ExpressResponse,
|
||||
} from "express";
|
||||
|
||||
import {isRedirect, InternalHandler, AuthenticationRequired,
|
||||
AuthorizationDenied, Call,type Method, type ProcessedRoute,methodParser, type Result, type Route,massageMethod } from "./types";
|
||||
import { runWithContext } from "./context";
|
||||
import { Session } from "./auth";import { request } from "./request";
|
||||
import { match } from "path-to-regexp";
|
||||
|
||||
type ProcessedRoutes= {[K in Method]: ProcessedRoute[] }
|
||||
const processRoutes=(routes:Route[]) :ProcessedRoutes => {
|
||||
const retval:ProcessedRoutes= {
|
||||
GET: [],
|
||||
POST: [],
|
||||
PUT: [],
|
||||
PATCH: [],
|
||||
DELETE: [],
|
||||
};
|
||||
|
||||
routes.forEach((route: Route, _idx: number, _allRoutes: Route[]) => {
|
||||
// const pattern /*: URLPattern */ = new URLPattern({ pathname: route.path });
|
||||
const matcher = match<Record<string, string>>(route.path);
|
||||
const methodList = route.methods;
|
||||
|
||||
const handler: InternalHandler = async (
|
||||
expressRequest: ExpressRequest,
|
||||
): Promise<Result> => {
|
||||
const method = massageMethod(expressRequest.method);
|
||||
|
||||
console.log("method", method);
|
||||
|
||||
if (!methodList.includes(method)) {
|
||||
// XXX: Worth asserting this?
|
||||
}
|
||||
|
||||
console.log("request.originalUrl", expressRequest.originalUrl);
|
||||
|
||||
// Authenticate the request
|
||||
const auth = await request.auth.validateRequest(expressRequest);
|
||||
|
||||
const req: Call = {
|
||||
pattern: route.path,
|
||||
path: expressRequest.originalUrl,
|
||||
method,
|
||||
parameters: { one: 1, two: 2 },
|
||||
request: expressRequest,
|
||||
user: auth.user,
|
||||
session: new Session(auth.session, auth.user),
|
||||
};
|
||||
|
||||
try {
|
||||
const retval = await runWithContext({ user: auth.user }, () =>
|
||||
route.handler(req),
|
||||
);
|
||||
return retval;
|
||||
} catch (error) {
|
||||
// Handle authentication errors
|
||||
if (error instanceof AuthenticationRequired) {
|
||||
return {
|
||||
code: httpCodes.clientErrors.Unauthorized,
|
||||
contentType: contentTypes.application.json,
|
||||
result: JSON.stringify({
|
||||
error: "Authentication required",
|
||||
}),
|
||||
};
|
||||
}
|
||||
if (error instanceof AuthorizationDenied) {
|
||||
return {
|
||||
code: httpCodes.clientErrors.Forbidden,
|
||||
contentType: contentTypes.application.json,
|
||||
result: JSON.stringify({ error: "Access denied" }),
|
||||
};
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
for (const [_idx, method] of methodList.entries()) {
|
||||
const pr: ProcessedRoute = { matcher, method, handler };
|
||||
|
||||
retval[method].push(pr);
|
||||
}
|
||||
});
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
export{processRoutes}
|
||||
Reference in New Issue
Block a user