简体   繁体   中英

How to give custom error message in api response

I want to give a proper error handling, in my endpoint, in this case i try to do some syntax error in raw json body request in postman.

i dont want the response like this

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <title>Error</title>
</head>

<body>
    <pre>SyntaxError: Unexpected token a in JSON at position 125<br> &nbsp; &nbsp;at JSON.parse (&lt;anonymous&gt;)<br> &nbsp; &nbsp;at parse (/Users/admin/Documents/NEW-SOURCE/security/boost-svc-consumer/node_modules/body-parser/lib/types/json.js:89:19)<br> &nbsp; &nbsp;at /Users/admin/Documents/NEW-SOURCE/security/boost-svc-consumer/node_modules/body-parser/lib/read.js:121:18<br> &nbsp; &nbsp;at invokeCallback (/Users/admin/Documents/NEW-SOURCE/security/boost-svc-consumer/node_modules/raw-body/index.js:224:16)<br> &nbsp; &nbsp;at done (/Users/admin/Documents/NEW-SOURCE/security/boost-svc-consumer/node_modules/raw-body/index.js:213:7)<br> &nbsp; &nbsp;at IncomingMessage.onEnd (/Users/admin/Documents/NEW-SOURCE/security/boost-svc-consumer/node_modules/raw-body/index.js:273:7)<br> &nbsp; &nbsp;at emitNone (events.js:106:13)<br> &nbsp; &nbsp;at IncomingMessage.emit (events.js:208:7)<br> &nbsp; &nbsp;at IncomingMessage.wrapped [as emit] (/Users/admin/Documents/NEW-SOURCE/security/boost-svc-consumer/node_modules/newrelic/lib/transaction/tracer/index.js:193:22)<br> &nbsp; &nbsp;at endReadableNT (_stream_readable.js:1064:12)<br> &nbsp; &nbsp;at _combinedTickCallback (internal/process/next_tick.js:138:11)<br> &nbsp; &nbsp;at process._tickCallback (internal/process/next_tick.js:180:9)</pre>
</body>

</html>

I want give some custom message. Like "Unknown error or syntax error in json request", I gave try catch in my controller fucntion but looks like try catch doesnt catch it" it throw error befor it come in to the try catch block.

do you know hot to do it?

Thanks in advance

Yes, you can do it easily if you are working with express.

Below is the code of my api server that you can find the sources HERE .

I'm using typescript but the same can be achieved with javascript at 0 cost.

ErrorMiddleware

This middleware can catch any error thrown. As you can see there is a specific SyntaxError that can catch malformed JSON and reply to the client.

import { Response, Request, NextFunction } from 'express';
import { UnauthorizedError } from 'express-jwt';
import logger from '@app/logger';
import { EnvUtil } from '@app/util';
import { ResponseHelper, HttpStatusCode } from '@app/helper';
import { EmptyFileError } from '@app/common/error';

export default class ErrorMiddleware {
  public static handle(err: Error, _req: Request, res: Response, _next: NextFunction): void {
    if (err instanceof UnauthorizedError) {
      logger.warn(`Authentication with JWT failed due to ${err.message}`);
      ResponseHelper.send(res, HttpStatusCode.UNAUTHORIZED);
    } else if (err instanceof SyntaxError) {
      logger.warn(`Malformed JSON due to ${err.message}`);
      ResponseHelper.send(res, HttpStatusCode.BAD_REQUEST, [err.message]);
    } else {
      logger.error(`Internal Server error due to ${err.message}`);
      ResponseHelper.send(
        res,
        HttpStatusCode.INTERNAL_SERVER_ERROR,
        EnvUtil.isDevelopment() ? err.stack : undefined
      );
    }
  }
}

Express app

When you create the Express app remember to register (with use) the ErrorMiddleware. I register the error middleware Here .

import express from 'express';
import bodyParser from 'body-parser';
import { ErrorMiddleware } from '@app/middleware';

const app = express();
// JSON body parser
app.use(bodyParser.json())
// Before error middleware configure all your express app
app.use(ErrorMiddleware.handle);

ResponseHelper

This class handle the response given the res express parameter, http status code you want to return and some data (optional). You can find the implementation Here .

You can find the implementation of httpStatusCode Here

As you can see the interface Response is the mapping for all API responses with:

  1. status: string success or fail
  2. is_success: boolean true if is success, false otherwise
  3. status_code: http status code
  4. status_code_name: http status code description
  5. data: the data (any type)
import { Response as ExpressResponse } from 'express';
import HttpStatusCode, { Status } from './httpStatusCode';

export interface Response {
  status: Status;
  is_success: boolean;
  status_code: number;
  status_code_name: string;
  data: object;
}

export default class ResponseHelper {
  public static send(
    res: ExpressResponse,
    httpStatusCode: HttpStatusCode,
    data: any = undefined
  ): void {
    res
      .status(httpStatusCode.code)
      .json(<Response>{
        status: httpStatusCode.status(),
        is_success: httpStatusCode.isSuccess(),
        status_code: httpStatusCode.code,
        status_code_name: httpStatusCode.name,
        data,
      })
      .end();
  }
}

You can test the application sending malformed JSON at the following URL: https://racer-2020.herokuapp.com/api/v1/car

The error response will be the following:

{
    "status": "fail",
    "is_success": false,
    "status_code": 400,
    "status_code_name": "Bad Request",
    "data": [
        "Unexpected end of JSON input"
    ]
}

In the source code you can find other middleware that handle for example a not found route path.

Hope it helps:)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM