如何从Loopback 4中的控制器返回错误?

时间:2019-03-22 22:57:14

标签: error-handling loopbackjs

我有一个控制器方法

// ... inside a controller class

@get('/error', {})
async error() {
  throw new Error("This is the error text");
}

我从此错误前端得到的响应是:

  

{     “错误”:{       “ statusCode”:500,       “消息”:“内部服务器错误”     }   }

我希望出现的错误是:

  

{     “错误”:{       “ statusCode”:500,       “ message”:“这是错误文本”     }   }

如何从Loopback 4中的控制器返回错误?

3 个答案:

答案 0 :(得分:2)

LoopBack小组的您好

在控制器或存储库中,应完全按照问题所示抛出错误。

现在,当LoopBack捕获到错误时,它将调用reject操作来处理错误。 reject的内置实现通过console.error记录一条消息,并返回带有4xx / 5xx错误代码和描述错误的响应正文的HTTP响应。

默认情况下,LoopBack隐藏HTTP响应中的实际错误消息。这是一项安全措施,可防止服务器泄漏潜在的敏感数据(无法打开文件的路径,无法访问后端服务的IP地址)。

在后台,我们使用strong-error-handler将Error对象转换为HTTP响应。该模块提供两种模式:

  • 生产模式(默认):5xx错误不包括任何其他信息,4xx错误包括部分信息。
  • 调试模式(debug: true):响应中包括所有错误详细信息,包括完整的堆栈跟踪。

可以通过将以下行添加到Application构造函数来启用调试模式:

this.bind(RestBindings.ERROR_WRITER_OPTIONS).to({debug: true});

在我们的文档中了解更多信息:Sequence >> Handling errors

或者,您可以实现自己的错误处理程序并将其绑定为序列操作reject。请参阅我们文档中的Customizing sequence actions

export class MyRejectProvider implements Provider<Reject> {
  constructor(
    @inject(RestBindings.SequenceActions.LOG_ERROR)
    protected logError: LogError,
    @inject(RestBindings.ERROR_WRITER_OPTIONS, {optional: true})
    protected errorWriterOptions?: ErrorWriterOptions,
  ) {}

  value(): Reject {
    return (context, error) => this.action(context, error);
  }

  action({request, response}: HandlerContext, error: Error) {
    const err = <HttpError>error;

    const statusCode = err.statusCode || err.status || 500;
    const body = // convert err to plain data object

    res.statusCode = statusCode;
    res.setHeader('Content-Type', 'application/json; charset=utf-8');
    res.end(JSON.stringify(body), 'utf-8');

    this.logError(error, statusCode, request);
  }
}

答案 1 :(得分:0)

对于我的情况,我在catch文件中找到了sequence.ts。在捕获中,它检查错误的状态码是否为4xx,如果不是,则返回一个匿名500。

这是我正在寻找的执行逻辑的代码:

// sequence.ts
...
} catch (err) {
  console.log(err);
  let code: string = (err.code || 500).toString();
  if (code.length && code[0] === '4') {
    response.status(Number(code) || 500);
    return this.send(response, {
      error: {
        message: err.message,
        name: err.name || 'UnknownError',
        statusCode: code
      }
    });
  }
  return this.reject(context, err);
}
...

这是您告诉它怎么做的方法:

// ... inside a controller class

@get('/error', {})
async error() {
  throw {
    code: 400,
    message: "This is the error text",
    name: "IntentionalError"
  }
}

答案 2 :(得分:0)

如果只想显示错误消息,则只需扩展Error对象并将其抛出,如下所示。 (Loopback文档始终没有提到这一点)

避免使用5xx错误,而使用4xx错误向用户展示一些重要的东西是最佳实践,因此Loopback4的实现是这样的。

class NotFound extends Error {
  statusCode: number

  constructor(message: string) {
    super(message)
    this.statusCode = 404
  }
}

...

if (!await this.userRepository.exists(id)) {
  throw new NotFound('user not found')
}