Skip to content

Commit e974e1b

Browse files
committed
Merge branch '22-handle-errors-thrown-by-a-routes-handle' into auth
2 parents e47ead4 + 3d10f97 commit e974e1b

File tree

3 files changed

+51
-2
lines changed

3 files changed

+51
-2
lines changed

src/Server.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {Authenticator} from "./auth/Authenticator.js";
55
import {Request} from "./Request.js";
66
import {EmptyResponse} from "./response/index.js";
77
import {Response} from "./response/Response.js";
8+
import {ThrowableResponse} from "./response/ThrowableResponse.js";
89
import {RouteRegistry} from "./routing/RouteRegistry.js";
910
import {ServerErrorRegistry} from "./ServerErrorRegistry.js";
1011

@@ -89,9 +90,13 @@ class Server<A> extends EventEmitter<Server.Events> {
8990
await this.errors._get(ServerErrorRegistry.ErrorCodes.BAD_URL, null)._send(res);
9091
return;
9192
}
93+
9294
if (e instanceof Request.SocketClosedError)
9395
return;
94-
throw e;
96+
97+
this.emit("error", e as any);
98+
this.errors._get(ServerErrorRegistry.ErrorCodes.INTERNAL, null)._send(res, this);
99+
return;
95100
}
96101

97102
for (const [key, value] of this.globalHeaders)
@@ -107,7 +112,13 @@ class Server<A> extends EventEmitter<Server.Events> {
107112
response = await this.routes.handle(apiRequest);
108113
}
109114
catch (e) {
110-
if (e instanceof RouteRegistry.NoRouteError)
115+
if (e instanceof ThrowableResponse) {
116+
response = e.getResponse();
117+
const cause = e.getError();
118+
if (cause !== null)
119+
this.emit("error", cause);
120+
}
121+
else if (e instanceof RouteRegistry.NoRouteError)
111122
response = this.errors._get(ServerErrorRegistry.ErrorCodes.NO_ROUTE, apiRequest);
112123
else {
113124
this.emit("error", e as any);

src/response/ThrowableResponse.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import {Response} from "./Response.js";
2+
3+
/**
4+
* An (error) response that is thrown. Will be caught by the server and sent to the client.
5+
*/
6+
export class ThrowableResponse<T extends Response> extends Error {
7+
public override name = ThrowableResponse.name;
8+
9+
/**
10+
* The response to send to the client.
11+
*/
12+
protected readonly response: T;
13+
14+
/**
15+
* An optional error to emit on the server’s error event.
16+
*/
17+
protected readonly error: Error | null;
18+
19+
/**
20+
* Create a new throwable response.
21+
* @param response The response to send to the client.
22+
* @param [error] An optional error to emit on the server’s error event.
23+
*/
24+
public constructor(response: T, error?: Error) {
25+
super();
26+
this.response = response;
27+
this.error = error ?? null;
28+
}
29+
30+
public getResponse(): T {
31+
return this.response;
32+
}
33+
34+
public getError(): Error | null {
35+
return this.error;
36+
}
37+
}

src/response/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ export * from "./EmptyResponse.js";
44
export * from "./JsonResponse.js";
55
export * from "./Response.js";
66
export * from "./TextResponse.js";
7+
export * from "./ThrowableResponse.js";

0 commit comments

Comments
 (0)