middleware works as it should! With recursion, which I hate :)
This commit is contained in:
4928
client/Cargo.lock
generated
Normal file
4928
client/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -7,12 +7,14 @@ import { ok, ResultFromJSON } from "@shared/utils/result.ts";
|
||||
import { ResultResponseFromJSON } from "@src/lib/context.ts";
|
||||
import admin from "@src/lib/admin.ts";
|
||||
import UsbipManager from "@shared/utils/usbip.ts";
|
||||
import loggerMiddleware from "@src/middleware/logger.ts";
|
||||
|
||||
const router = new HttpRouter();
|
||||
|
||||
const views = Deno.cwd() + "/views/";
|
||||
const eta = new Eta({ views });
|
||||
|
||||
router.use(loggerMiddleware);
|
||||
router.use(rateLimitMiddleware);
|
||||
router.use(authMiddleware);
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@ type RequestHandler<S extends string> = (
|
||||
export type Middleware = (
|
||||
c: Context<string>,
|
||||
next: () => Promise<void>,
|
||||
) => Promise<Response | undefined> | Response | undefined;
|
||||
) => Promise<Response | void> | Response | void;
|
||||
|
||||
type MethodHandlers<S extends string> = Partial<
|
||||
Record<string, RequestHandler<S>>
|
||||
@ -19,7 +19,7 @@ const DEFAULT_NOT_FOUND_HANDLER = () => new Response("404 Not found");
|
||||
class HttpRouter {
|
||||
routerTree = new RouterTree<MethodHandlers<any>>();
|
||||
pathPreprocessor?: (path: string) => string;
|
||||
middlewareChain: Middleware[] = [];
|
||||
middlewares: Middleware[] = [];
|
||||
defaultNotFoundHandler: RequestHandler<string> = DEFAULT_NOT_FOUND_HANDLER;
|
||||
|
||||
setPathProcessor(processor: (path: string) => string) {
|
||||
@ -27,7 +27,7 @@ class HttpRouter {
|
||||
}
|
||||
|
||||
use(mw: Middleware): HttpRouter {
|
||||
this.middlewareChain.push(mw);
|
||||
this.middlewares.push(mw);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -99,23 +99,58 @@ class HttpRouter {
|
||||
): Promise<Response> {
|
||||
const c = new Context(req, connInfo, {});
|
||||
|
||||
let i = 0;
|
||||
const mw = this.middlewareChain[i++];
|
||||
|
||||
const path = this.pathPreprocessor
|
||||
? this.pathPreprocessor(c.path)
|
||||
: c.path;
|
||||
|
||||
return await this.routerTree
|
||||
let params: Params<string> = {};
|
||||
|
||||
const handler = this.routerTree
|
||||
.find(path)
|
||||
.andThen((routeMatch) => {
|
||||
const { value, params } = routeMatch;
|
||||
const handler = value[req.method];
|
||||
return handler
|
||||
? some(handler(Context.setParams(c, params)))
|
||||
: none;
|
||||
const { value: handlers, params: paramsMatched } = routeMatch;
|
||||
params = paramsMatched;
|
||||
const handler = handlers[req.method];
|
||||
return handler ? some(handler) : none;
|
||||
})
|
||||
.unwrapOrElse(() => this.defaultNotFoundHandler(c));
|
||||
.unwrapOrElse(() => this.defaultNotFoundHandler);
|
||||
|
||||
const cf = await this.executeMiddlewareChain(
|
||||
this.middlewares,
|
||||
handler,
|
||||
Context.setParams(c, params),
|
||||
);
|
||||
|
||||
return cf.res;
|
||||
}
|
||||
|
||||
private async executeMiddlewareChain<S extends string>(
|
||||
middlewares: Middleware[],
|
||||
handler: RequestHandler<S>,
|
||||
c: Context<S>,
|
||||
) {
|
||||
let currentIndex = -1;
|
||||
|
||||
const dispatch = async (index: number): Promise<void> => {
|
||||
currentIndex = index;
|
||||
|
||||
if (index < middlewares.length) {
|
||||
const middleware = middlewares[index];
|
||||
|
||||
const result = await middleware(c, () => dispatch(index + 1));
|
||||
|
||||
if (result !== undefined) {
|
||||
c.res = await Promise.resolve(result);
|
||||
}
|
||||
} else {
|
||||
const res = await handler(c);
|
||||
c.res = res;
|
||||
}
|
||||
};
|
||||
|
||||
await dispatch(0);
|
||||
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@ import admin from "@lib/admin.ts";
|
||||
|
||||
const LOGIN_PATH = "/login";
|
||||
|
||||
const authMiddleware: Middleware = (c) => {
|
||||
const authMiddleware: Middleware = async (c, next) => {
|
||||
const token = c.cookies.get("token");
|
||||
const isValid = token
|
||||
.map((token) => admin.sessions.verifyToken(token))
|
||||
@ -11,9 +11,8 @@ const authMiddleware: Middleware = (c) => {
|
||||
const path = c.path;
|
||||
|
||||
if (path.startsWith("/public")) {
|
||||
return;
|
||||
}
|
||||
|
||||
await next();
|
||||
} else {
|
||||
if (path !== LOGIN_PATH && !isValid) {
|
||||
return c.redirect("/login");
|
||||
}
|
||||
@ -21,6 +20,9 @@ const authMiddleware: Middleware = (c) => {
|
||||
if (path === LOGIN_PATH && isValid) {
|
||||
return c.redirect("");
|
||||
}
|
||||
|
||||
await next();
|
||||
}
|
||||
};
|
||||
|
||||
export default authMiddleware;
|
||||
|
||||
9
server/src/middleware/logger.ts
Normal file
9
server/src/middleware/logger.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { Middleware } from "@lib/router.ts";
|
||||
|
||||
const loggerMiddleware: Middleware = async (c, next) => {
|
||||
console.log(c.req.method, c.path);
|
||||
await next();
|
||||
console.log(c.res.status);
|
||||
};
|
||||
|
||||
export default loggerMiddleware;
|
||||
@ -8,7 +8,7 @@ const requestCounts: Partial<
|
||||
const MAX_REQUESTS_PER_WINDOW = 300;
|
||||
const RATE_LIMIT_WINDOW = 60000;
|
||||
|
||||
const rateLimitMiddleware: Middleware = (c) => {
|
||||
const rateLimitMiddleware: Middleware = async (c, next) => {
|
||||
const hostnameOpt = c.hostname;
|
||||
|
||||
if (hostnameOpt.isSome()) {
|
||||
@ -19,15 +19,9 @@ const rateLimitMiddleware: Middleware = (c) => {
|
||||
|
||||
if (!clientCount || now - clientCount.lastReset > RATE_LIMIT_WINDOW) {
|
||||
requestCounts[hostname] = { count: 1, lastReset: now };
|
||||
return;
|
||||
}
|
||||
|
||||
if (clientCount.count < MAX_REQUESTS_PER_WINDOW) {
|
||||
} else if (clientCount.count < MAX_REQUESTS_PER_WINDOW) {
|
||||
clientCount.count++;
|
||||
return;
|
||||
}
|
||||
|
||||
if (c.preferredType.isSome()) {
|
||||
} else if (c.preferredType.isSome()) {
|
||||
log.info(`client ${hostname} is rate limeted`);
|
||||
switch (c.preferredType.value) {
|
||||
case "html": {
|
||||
@ -46,11 +40,13 @@ const rateLimitMiddleware: Middleware = (c) => {
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return new Response("429 Too Many Request", {
|
||||
status: 429,
|
||||
});
|
||||
}
|
||||
}
|
||||
await next();
|
||||
};
|
||||
|
||||
export default rateLimitMiddleware;
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
quantile
|
||||
|
||||
quntile
|
||||
Reference in New Issue
Block a user