Type |聽Version
---|---
Question | 4.x
Express default error handling responds with the below.
Cannot GET /
I want to convert this to a JSON response but I am unable to add a errorHandler in the ServerLoader-$afterRoutesInit. Can you please advise?
Hello @virus2016 ,
You can do that with overiding GlobalErrorHandlerMiddleware. Here the documentation: http://tsed.io/#/docs/middlewares/override/global-error-handler
See you ;)
@Romakita Overriding GlobalErrorHandlerMiddleware doesn't seem to have any effects on 404. If the server is hit with a route that isn't present, the Overridden error handler isn't getting called. Instead we are getting the following html page:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>Cannot GET /rest/asdff</pre>
</body>
</html>
Hello I've added a working example on the website: http://tsed.io/tutorials/not-found-page.html
See you,
Romain
@Romakita
Thanks, that worked. Out of curiosity, in your previous comments here you mentioned to just import middleware like : import "./middlewares/custom-middleware"
How come I have to use the line: this.use(NotFoundMiddleware); in this example?
Because it is not overriding an existing middleware?
In fact, express.js respond 404 after it has executed all routes and middlewares. So 404 in term of express.js isn鈥檛 an error.
To customize 404, we just have to register a new middleware on $afterRouteInit (or $onServerReady) hook. $afterRoutesInit in the ts.ed lifecycle come after all registration routes and just before the GlobalErrorHandlerMiddleware (which handle all errors).
Override midleware is a feature that allow developper to change the Ts.ED middleware like GlobalErrorHandler by is own middleware. Here because the 404 exception is emitted after all middlewares and routes, the GlobalErrorHandler never catch this exception :)
I hope my explanation are clear ;)
See you
Romain
@Romakita
How do you handle errors via Ajax? I've tried all the errors in your library and none of them have returned a single JSON. In the end I had to do it just like Express does.
@Post('/create')
async create (@BodyParams() user: User, @Res() res: Express.Response): Promise<any> {
try {
return await this.userRepository.save(user)
} catch (error) {
res.status(400).json({
success: false,
message: error.message
});
}
}
or is there another way? I think you should make an example of CRUD API, where you can see the error handling correctly. I've seen some examples, but none of them have solved my doubts.
But I guess I'll just have to do it the way I set my example, right?
Hello @chiqui3d
You have to override GlobalErrorHandlerMiddleware to change the error mapping.
Here the link to this middleware: https://tsed.io/docs/middlewares.html#handle-error
The current middleware generate an HTML response. So change it by json:
import {Err, Middleware, Req, Res} from "@tsed/common";
import {Exception} from "ts-httpexceptions";
import {$log} from "ts-log-debug";
@Middleware()
export class GlobalErrorHandlerMiddleware {
use(
@Err() error: any,
@Req() request: Req,
@Res() response: Res
): any {
if (response.headersSent) {
throw error;
}
const toHTML = (message = "") => message.replace(/\n/gi, "<br />");
if (error instanceof Exception) {
$log.error("" + error);
response.status(error.status).send(toHTML(error.message)); // here
return;
}
if (typeof error === "string") {
response.status(404).send(toHTML(error));
return;
}
$log.error("" + error);
response.status(error.status || 500).send("Internal Error");
return;
}
}
Thanks @Romakita
How should I apply it? I've applied it, but it doesn't work.
//src/Middleware/GlobalErrorHandlerMiddleware.ts
import { Err, Middleware, Req, Res } from '@tsed/common'
import { Exception } from 'ts-httpexceptions'
import { $log } from 'ts-log-debug'
@Middleware()
export class GlobalErrorHandlerMiddleware {
use (@Err() error: any, @Req() request: Req, @Res() response: Res): any {
$log.error('' + error)
console.log('Customer global Error')
if (response.headersSent) {
throw error
}
if (typeof error === 'string') {
error['message'] = error;
}
if (error instanceof Exception) {
response.status(error.status || 500).json({
message: error.message || 'Internal Custom Error'
})
}
return
}
}
// src/Server.ts
import { GlobalErrorHandlerMiddleware } from'./Middleware/GlobalErrorHandlerMiddleware';
// ....
$beforeRoutesInit (): void | Promise<any> {
this
.use(GlobalAcceptMimesMiddleware)
.use(GlobalErrorHandlerMiddleware)
.use(compress({}))
.use(methodOverride())
.use(cookieParser())
.use(bodyParser.json())
.use(bodyParser.urlencoded({ extended: true }))
.use(cors(corsOptions))
.use(Passport.initialize());
return null
}
Hello,
v4.x => http://v4.tsed.io/docs/middlewares/global-error-middleware.html
v5.x => https://tsed.io/docs/middlewares/override/global-error-handler.html
Example v5.x => https://github.com/amourlanne/express-tsed-boilerplate/blob/master/src/Middlewares/GlobalErrorHandlerMiddleware.ts
@amourlanne thanks very much,
I only need to put OverrideProvideras in your example
Yes sir ;)
Most helpful comment
Hello I've added a working example on the website: http://tsed.io/tutorials/not-found-page.html
See you,
Romain