7

我有一个控制器方法

// ... inside a controller class

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

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

{“错误”:{“状态代码”:500,“消息”:“内部服务器错误”}}

我希望错误是:

{ "error": { "statusCode": 500, "message": "这是错误文本" } }

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

4

4 回答 4

11

LoopBack 团队的问候

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

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

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

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

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

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

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

在我们的文档中了解更多信息:序列 >> 处理错误

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

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);
  }
}
于 2019-03-25T07:11:58.433 回答
3

如果您只想显示错误消息,只需扩展 Error 对象并将其抛出,如下所示。(环回文档无论如何都没有提到这一点)

避免使用 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')
}
于 2020-01-06T07:52:40.160 回答
2

对于我的情况,我catch在我的sequence.ts文件中找到了一个。在 catch 内部,它检查错误的状态码是否为 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"
  }
}
于 2019-03-25T15:58:37.070 回答
0

要抛出自定义验证错误,我使用此方法:

private static createError(msg: string, name?: string): HttpErrors.HttpError {
    const error = new HttpErrors['422'](msg);
    error.name = name ?? this.name;
    return error;
}

此处的捕获错误示例用于 defaultSequence,覆盖了句柄方法。但是现在的应用程序模板使用的是 MiddlewareSequence。

所以这里是一个例子,如何修改中间件序列中的响应,你可以使用这个例子:

import { Middleware, MiddlewareContext } from '@loopback/rest';

export const ErrorMiddleware: Middleware = async (middlewareCtx: MiddlewareContext, next) => {
    // const {response} = middlewareCtx;
    try {
        // Proceed with next middleware
        return await next();
    } catch (err) {
        // Catch errors from downstream middleware
        // How to catch specific error and how to send custom error response:
        if (HttpErrors.isHttpError(err) || (err as HttpErrors.HttpError).statusCode) {
            const code: string = (err.statusCode || 500).toString();
            if (code.length && code[0] === '4') {
                response.status(Number(code) || 500);
                return response.send({
                    error: {
                        message: err.message,
                        name: err.name || 'UnknownError',
                        statusCode: code
                    }
                });
            }
        }
        throw err;
    }
};

并在 application.ts 中注册中间件

this.middleware(ErrorMiddleware);
于 2021-11-04T08:24:49.357 回答