Skip to content

Commit

Permalink
add errorHandle property to class Router (#2)
Browse files Browse the repository at this point in the history
Resolves #1.
  • Loading branch information
EthanThatOneKid authored Apr 7, 2024
1 parent 6242beb commit 72715e2
Showing 1 changed file with 73 additions and 51 deletions.
124 changes: 73 additions & 51 deletions rt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,13 @@ export interface Handle<T extends string = string> {
(ctx: RouterContext<T>): Promise<Response> | Response;
}

/**
* ErrorHandle is called to handle an error.
*/
export interface ErrorHandle {
(error: Error): Promise<Response> | Response;
}

/**
* Route represents a the pairing of a matcher and a handler.
*/
Expand Down Expand Up @@ -114,71 +121,78 @@ type RouterInterface = Record<
export class Router implements RouterInterface {
public routes: Routes = [];
public defaultHandle?: Handle;
public errorHandle?: ErrorHandle;

/**
* fetch invokes the router for the given request.
*/
public async fetch(request: Request, i = 0): Promise<Response> {
const url = new URL(request.url);
while (i < this.routes.length) {
const route = this.routes[i];
const matchedMethod = route.match === undefined ||
typeof route.match !== "function" &&
(route.match.method === undefined ||
route.match.method === request.method);
if (!matchedMethod) {
i++;
continue;
}
try {
const url = new URL(request.url);
while (i < this.routes.length) {
const route = this.routes[i];
const matchedMethod = route.match === undefined ||
typeof route.match !== "function" &&
(route.match.method === undefined ||
route.match.method === request.method);
if (!matchedMethod) {
i++;
continue;
}

const matchedFn = typeof route.match === "function" &&
await route.match({ request, url });
const matchedPattern = route.match !== undefined &&
typeof route.match !== "function" &&
route.match.pattern !== undefined &&
route.match.pattern.exec(request.url);
let params: Record<string, string> = {};
if (matchedPattern) {
params = matchedPattern?.pathname
? Object.entries(matchedPattern.pathname.groups)
.reduce(
(groups, [key, value]) => {
if (value !== undefined) {
groups[key] = value;
}

return groups;
},
{} as { [key: string]: string },
)
: {};
}

// If the route matches, call it and return the response.
if (route.match === undefined || matchedFn || matchedPattern) {
return await route.handle({
request,
url,
params,
next: () => this.fetch(request, i + 1),
});
}

const matchedFn = typeof route.match === "function" &&
await route.match({ request, url });
const matchedPattern = route.match !== undefined &&
typeof route.match !== "function" &&
route.match.pattern !== undefined &&
route.match.pattern.exec(request.url);
let params: Record<string, string> = {};
if (matchedPattern) {
params = matchedPattern?.pathname
? Object.entries(matchedPattern.pathname.groups)
.reduce(
(groups, [key, value]) => {
if (value !== undefined) {
groups[key] = value;
}

return groups;
},
{} as { [key: string]: string },
)
: {};
i++;
}

// If the route matches, call it and return the response.
if (route.match === undefined || matchedFn || matchedPattern) {
return await route.handle({
if (this.defaultHandle !== undefined) {
return await this.defaultHandle({
request,
url,
params,
next: () => this.fetch(request, i + 1),
params: {},
next: () => {
throw new Error("next() called from default handler");
},
});
}

i++;
}

if (this.defaultHandle !== undefined) {
return await this.defaultHandle({
request,
url,
params: {},
next: () => {
throw new Error("next() called from default handler");
},
});
} catch (error) {
if (this.errorHandle !== undefined) {
return await this.errorHandle(error);
}
}

throw new Error("Not found");
return new Response("Internal Server Error", { status: 500 });
}

/**
Expand Down Expand Up @@ -225,6 +239,14 @@ export class Router implements RouterInterface {
return this;
}

/**
* error sets the router's error handler.
*/
public error(handle: ErrorHandle | undefined): this {
this.errorHandle = handle;
return this;
}

/**
* connect appends a router for the CONNECT method to the router.
*/
Expand Down

0 comments on commit 72715e2

Please sign in to comment.