Skip to content

Commit

Permalink
fixup! tmp: r2, origin middleware init
Browse files Browse the repository at this point in the history
  • Loading branch information
flakey5 committed Jun 21, 2024
1 parent 0666fe4 commit 7fc1b5e
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 39 deletions.
7 changes: 6 additions & 1 deletion src/middleware/middleware.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { Context } from '../context';

export type MiddlewareNext = () => Promise<Response>;

export interface Middleware {
handle(
request: Request,
next: (request: Request) => Promise<Response>
ctx: Context,
next: MiddlewareNext
): Promise<Response>;
}
2 changes: 2 additions & 0 deletions src/middleware/originMiddleware.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { Context } from 'toucan-js/dist/types';
import { Middleware } from './middleware';

export class R2Middleware implements Middleware {
handle(
request: Request,
ctx: Context,
next?: (request: Request) => Promise<Response>
): Promise<Response> {
throw new Error();
Expand Down
24 changes: 10 additions & 14 deletions src/middleware/r2Middleware.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,25 @@
import { Context } from '../context';
import { R2Provider } from '../providers/r2Provider';
import responses from '../responses';
import { isDirectoryPath } from '../utils/path';
import { parseUrl } from '../utils/request';
import { Middleware } from './middleware';
import { Middleware, MiddlewareNext } from './middleware';

// @ts-expect-error ctx
const r2Provider = new R2Provider();

export class R2Middleware implements Middleware {
handle(
request: Request,
next: (request: Request) => Promise<Response>
ctx: Context,
): Promise<Response> {
try {
switch (request.method) {
case 'HEAD':
return head(request);
default:
throw new Error(
`${request.method} ${request.url} unexpectedly mapped to R2Middleware`
);
}
} catch (err) {
// TODO log
return next(request);
switch (request.method) {
case 'HEAD':
return head(request);
default:
throw new Error(
`${request.method} ${request.url} unexpectedly mapped to R2Middleware`
);
}
}
}
Expand Down
62 changes: 38 additions & 24 deletions src/routes/router.ts
Original file line number Diff line number Diff line change
@@ -1,48 +1,62 @@
import { AutoRouter } from 'itty-router';
import { AutoRouter, IRequest } from 'itty-router';
import { Middleware } from '../middleware/middleware';
import { Context } from '../context';

export class Router {
private itty = AutoRouter();
private notFoundMiddleware = new NotFoundMiddleware();
private itty = AutoRouter<IRequest, [Context]>();

handle(request: Request): Promise<Response> {
return this.itty.fetch(request);
}

head(endpoint: string, middlewares: Middleware[]): void {
const middlewareChain = buildMiddlewareChain(middlewares);

this.itty.head(endpoint, async (req, ctx) => {
return middlewareChain(req, ctx);
});
}

get(endpoint: string, middlewares: Middleware[]): void {
const root = buildMiddlewareChain(middlewares, this.notFoundMiddleware);
const middlewareChain = buildMiddlewareChain(middlewares);

this.itty.get(endpoint, async req => {
return root.middleware.handle(req, root.next);
this.itty.get(endpoint, async (req, ctx) => {
return middlewareChain(req, ctx);
});
}
}

interface MiddlewareChain {
middleware: Middleware;
next: (req: Request) => Promise<Response>;
}
type MiddlewareChain = (request: Request, ctx: Context) => Promise<Response>;

function buildMiddlewareChain(
middlewares: Middleware[],
fallbackMiddleware: Middleware
): MiddlewareChain {
// @ts-expect-error next is undefined
let root: MiddlewareChain = { middleware: fallbackMiddleware };
function buildMiddlewareChain(middlewares: Middleware[]): MiddlewareChain {
let root: MiddlewareChain = () => {
throw new Error('reached the end of middleware chain');
};

for (let i = middlewares.length - 1; i >= 0; i--) {
root = {
middleware: middlewares[i],
// @ts-expect-error next might be undefined
next: root.middleware.handle,
root = (request, ctx) => {
const middleware = errorHandled(middlewares[i]);

return middleware.handle(request, ctx, () => {
return root(request, ctx);
});
};
}

return root;
}

class NotFoundMiddleware implements Middleware {
async handle(_: Request): Promise<Response> {
return new Response('Not found', { status: 404 });
}
function errorHandled(middleware: Middleware): Middleware {
const wrapper: Middleware = {
handle(request: Request, ctx: Context, next) {
try {
return middleware.handle(request, ctx, next);
} catch (err) {
// TODO send error to sentry
return next();
}
},
};

return wrapper;
}

0 comments on commit 7fc1b5e

Please sign in to comment.