Skip to content

Commit 6d99ef6

Browse files
twittwerNoNameProvided
authored andcommitted
feat(ErrorHandling): add support for custom toJSON method in errors
1 parent eabc592 commit 6d99ef6

File tree

3 files changed

+63
-1
lines changed

3 files changed

+63
-1
lines changed

README.md

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -693,7 +693,30 @@ There are set of prepared errors you can use:
693693
* NotFoundError
694694
* UnauthorizedError
695695

696-
You can also create and use your own errors by extending `HttpError` class.
696+
697+
You can also create and use your own errors by extending `HttpError` class.
698+
To define the data returned to the client, you could define a toJSON method in your error.
699+
700+
```typescript
701+
class DbError extends HttpError {
702+
public operationName: string;
703+
public args: any[];
704+
705+
constructor(operationName: string, args: any[] = []) {
706+
super(500);
707+
Object.setPrototypeOf(this, DbError.prototype);
708+
this.operationName = operationName;
709+
this.args = args; // can be used for internal logging
710+
}
711+
712+
toJSON() {
713+
return {
714+
status: this.httpCode,
715+
failedOperation: this.operationName
716+
}
717+
}
718+
}
719+
```
697720

698721
#### Enable CORS
699722

src/driver/BaseDriver.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,9 @@ export abstract class BaseDriver {
150150
if (!this.isDefaultErrorHandlingEnabled)
151151
return error;
152152

153+
if (typeof error.toJSON === "function")
154+
return error.toJSON();
155+
153156
let processedError: any = {};
154157
if (error instanceof Error) {
155158
const name = error.name && error.name !== "Error" ? error.name : error.constructor.name;

test/functional/express-error-handling.spec.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {Middleware} from "../../src/decorator/Middleware";
66
import {UseAfter} from "../../src/decorator/UseAfter";
77
import {ExpressErrorMiddlewareInterface} from "../../src/driver/express/ExpressErrorMiddlewareInterface";
88
import {NotFoundError} from "../../src/http-error/NotFoundError";
9+
import {HttpError} from "../../src/http-error/HttpError";
910
const chakram = require("chakram");
1011
const expect = chakram.expect;
1112

@@ -54,6 +55,25 @@ describe("express error handling", () => {
5455

5556
}
5657

58+
class ToJsonError extends HttpError {
59+
public publicData: string;
60+
public secretData: string;
61+
62+
constructor(httpCode: number, publicMsg?: string, privateMsg?: string) {
63+
super(httpCode);
64+
Object.setPrototypeOf(this, ToJsonError.prototype);
65+
this.publicData = publicMsg || "public";
66+
this.secretData = privateMsg || "secret";
67+
}
68+
69+
toJSON() {
70+
return {
71+
status: this.httpCode,
72+
publicData: `${this.publicData} (${this.httpCode})`
73+
}
74+
}
75+
}
76+
5777
@JsonController()
5878
class ExpressErrorHandlerController {
5979

@@ -97,6 +117,11 @@ describe("express error handling", () => {
97117
return "1234";
98118
}
99119

120+
@Get("/stories")
121+
stories() {
122+
throw new ToJsonError(503, "sorry, try it again later", "impatient user");
123+
}
124+
100125
}
101126
});
102127

@@ -154,4 +179,15 @@ describe("express error handling", () => {
154179
});
155180
});
156181

182+
it("should process JsonErrors by their toJSON method if it exists", () => {
183+
return chakram
184+
.get("http://127.0.0.1:3001/stories")
185+
.then((response: any) => {
186+
expect(response).to.have.status(503);
187+
expect(response.body).to.have.property("status").and.equals(503);
188+
expect(response.body).to.have.property("publicData").and.equals("sorry, try it again later (503)");
189+
expect(response.body).to.not.have.property("secretData");
190+
});
191+
});
192+
157193
});

0 commit comments

Comments
 (0)