Реализация фильтра ошибок Zuul от Netflix - PullRequest
0 голосов
/ 30 апреля 2019

Каким будет пример реализации фильтра ошибок для службы шлюза zuul от netflix?Все примеры, которые я нашел, были либо неправильными, либо слишком старыми для работы.

1 Ответ

0 голосов
/ 30 апреля 2019

Вы можете создать свой собственный настраиваемый фильтр и поставить этот фильтр для выполнения непосредственно перед SendErrorFilter Zuul по умолчанию, но иногда фильтр по умолчанию переопределяет ваше тело или ошибку HTTP. Я предпочитаю отключить фильтр по умолчанию, указав его в свойствах приложения:

zuul.SendErrorFilter.error.disable=true

Затем создайте свой собственный CustomSendErrorFilter, расширив его по умолчанию. Примером реализации будет:

@Component
public class SendErrorCustomFilter extends SendErrorFilter {

    private static final Logger LOG = LoggerFactory.getLogger(SendErrorCustomFilter.class);
    private static final String SERVLET_ERROR_STATUS_CODE = "javax.servlet.error.status_code";
    private static final String SERVLET_ERROR_EXCEPTION = "javax.servlet.error.exception";
    private static final String SERVLET_ERROR_MESSAGE = "javax.servlet.error.message";

    @Value("${error.path:/error}")
    private String errorPath;

    @Override
    public Object run() {
        try {
            RequestContext ctx = RequestContext.getCurrentContext();
            ExceptionHolder exception = findZuulException(ctx.getThrowable());
            HttpServletRequest request = ctx.getRequest();
            Throwable cause = exception.getThrowable().getCause();
            int statusCode = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;

            if (causeIsIOError(cause)) {
                statusCode = HttpServletResponse.SC_CONFLICT;
            } else if (causeIsAuthorizationError(cause)) {
                statusCode = HttpServletResponse.SC_UNAUTHORIZED;
            }

            request.setAttribute(SERVLET_ERROR_STATUS_CODE, statusCode);

            LOG.warn("Error during filtering", cause);
            request.setAttribute(SERVLET_ERROR_EXCEPTION, cause);

            if (StringUtils.hasText(exception.getErrorCause())) {
                request.setAttribute(SERVLET_ERROR_MESSAGE, cause.getMessage());
            }

            RequestDispatcher dispatcher = request.getRequestDispatcher(this.errorPath);
            if (dispatcher != null) {
                ctx.set(SEND_ERROR_FILTER_RAN, true);
                if (!ctx.getResponse().isCommitted()) {
                    ctx.setResponseStatusCode(exception.getStatusCode());
                    dispatcher.forward(request, ctx.getResponse());
                }
            }

        } catch (Exception ex) {
            ReflectionUtils.rethrowRuntimeException(ex);
        }
        return null;
    }

    private boolean causeIsIOError(Throwable cause) {
        return cause instanceof InvalidTokenPayloadException
                || cause instanceof InvalidResponseBodyException;
    }

    public boolean causeIsAuthorizationError(Throwable cause) {
        return cause instanceof InvalidJWTTokenException ||
                cause instanceof NoPermissionForResourceException ||
                cause instanceof MissingAuthorizationHeaderException;
    }

Таким образом, вы получаете полный контроль над ошибкой, которая будет отправлена ​​обратно клиенту. Я извлек несколько методов, которые проверяют различные исключения и помещают разные ошибки HTTP в зависимости от этих исключений. Я использую причину исключения, потому что эти исключения заключены в исключение ZuulException.

...