【问题标题】:How do I hook into micronaut server on error handling from a filter?如何在过滤器的错误处理中连接到 micronaut 服务器?
【发布时间】:2020-08-03 19:06:09
【问题描述】:

对于我的 micronaut 服务器发出的任何 4xx 或 5xx 响应,我想记录响应状态代码和它所针对的端点。看起来过滤器是一个很好的地方,但我似乎无法弄清楚如何插入 onError 处理

例如,这个过滤器

@Filter("/**")
class RequestLoggerFilter: OncePerRequestHttpServerFilter() {
  companion object {
    private val log = LogManager.getLogger(RequestLoggerFilter::class.java)
  }

  override fun doFilterOnce(request: HttpRequest<*>, chain: ServerFilterChain): Publisher<MutableHttpResponse<*>>? {
    return Publishers.then(chain.proceed(request), ResponseLogger(request))
  }

  class ResponseLogger(private val request: HttpRequest<*>): Consumer<MutableHttpResponse<*>> {
    override fun accept(response: MutableHttpResponse<*>) {
      log.info("Status: ${response.status.code} Endpoint: ${request.path}")
    }
  }
}

仅记录成功响应,而不记录 4xx 或 5xx 响应。 我如何让它与 onError 处理挂钩?

【问题讨论】:

  • 我确实检查了错误注释,也许这就是要走的路。但是,如果我创建一个捕获异常的通用错误处理程序,那么似乎我失去了一些免费提供的不错的默认错误处理(比如 io.micronaut.core.convert.exceptions.ConversionErrorException 被变成了一个错误的请求)。有没有办法让通用错误处理程序执行一些日志记录,然后将行为传递给通常会发生的情况? :我想我真正想要的是进行常规错误处理,然后将最终结果 - 400 记录到 /path

标签: kotlin micronaut


【解决方案1】:

您可以执行以下操作。创建您自己的 ApplicationException(扩展 RuntimeException),您可以在那里处理您的应用程序错误,特别是它们如何导致 http 错误代码。您的异常也可以保存状态代码。

例子:

class BadRequestException extends ApplicationException {
 
    public HttpStatus getStatus() {
        return HttpStatus.BAD_REQUEST;
    }
}

你可以有多个这个 ExceptionHandler 用于不同的目的。

@Slf4j
@Produces
@Singleton
@Requires(classes = {ApplicationException.class, ExceptionHandler.class})
public class ApplicationExceptionHandler implements ExceptionHandler<ApplicationException, HttpResponse> {

    @Override
    public HttpResponse handle(final HttpRequest request, final ApplicationException exception) {
        log.error("Application exception message={}, cause={}", exception.getMessage(), exception.getCause());
        final String message = exception.getMessage();
        final String code = exception.getClass().getSimpleName();
        final ErrorCode error = new ErrorCode(message, code);

        log.info("Status: ${exception.getStatus())} Endpoint: ${request.path}")

        return HttpResponse.status(exception.getStatus()).body(error);
    }
}

【讨论】:

    【解决方案2】:

    如果您尝试处理由 ConstraintExceptionHandler 产生的 400 (Bad Request) 等 Micronaut 原生异常,则需要 Replace bean 来执行此操作。

    我在这里发布了示例how to handle ConstraintExceptionHandler.

    如果您只想自己处理响应,则可以使用此映射每个响应代码(@Controller 上的示例,因此即使使用global flag,也不确定它是否适用于其他地方:

    @Error(status = HttpStatus.NOT_FOUND, global = true)  
    public HttpResponse notFound(HttpRequest request) {
      <...>
    }
    

    Example from Micronaut documentation.

    【讨论】:

      【解决方案3】:

      以下代码我用于在错误响应中添加自定义 cors 标头,在 doOnError 中您可以记录错误

      @Filter("/**")
      public class ResponseCORSAdder implements HttpServerFilter {
          @Override
          public Publisher<MutableHttpResponse<?>> doFilter(HttpRequest<?> request, ServerFilterChain chain) {
                  return this.trace(request) 
                  .switchMap(aBoolean -> chain.proceed(request))
                  .doOnError(error -> {
                      if (error instanceof MutableHttpResponse<?>) {
                          MutableHttpResponse<?> res = (MutableHttpResponse<?>) error;
                          addCorsHeaders(res);
                      }
                  })  
                  .doOnNext(res -> addCorsHeaders(res));
          }
      
              private MutableHttpResponse<?> addCorsHeaders(MutableHttpResponse<?> res) {
                  return res
                  .header("Access-Control-Allow-Origin", "*")
                  .header("Access-Control-Allow-Methods", "OPTIONS,POST,GET")
                  .header("Access-Control-Allow-Credentials", "true");
              }
      
              private Flowable<Boolean> trace(HttpRequest<?> request) {
                  return Flowable.fromCallable(() -> { 
                          // trace logic here, potentially performing I/O 
                          return true;
                  }).subscribeOn(Schedulers.io()); 
              }
      }
      

      【讨论】:

        猜你喜欢
        • 2011-04-16
        • 1970-01-01
        • 1970-01-01
        • 2019-10-08
        • 2021-04-20
        • 1970-01-01
        • 1970-01-01
        • 2022-06-02
        • 1970-01-01
        相关资源
        最近更新 更多