Netflix 的 Zuul 错误过滤器实现
Netflix's Zuul Error filter implementation
netflix 的 zuul 网关服务的错误过滤器实施示例是什么?我发现的所有示例要么不正确,要么太旧而无法使用。
您可以创建自己的自定义过滤器并将该过滤器放在 Zuul 的默认 SendErrorFilter 之前执行,但有时默认过滤器会覆盖您的正文或 HTTP 错误。
我更喜欢通过将其放入应用程序属性来禁用默认过滤器:
zuul.SendErrorFilter.error.disable=true
然后通过扩展默认的 CustomSendErrorFilter 创建您自己的 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 中。
netflix 的 zuul 网关服务的错误过滤器实施示例是什么?我发现的所有示例要么不正确,要么太旧而无法使用。
您可以创建自己的自定义过滤器并将该过滤器放在 Zuul 的默认 SendErrorFilter 之前执行,但有时默认过滤器会覆盖您的正文或 HTTP 错误。 我更喜欢通过将其放入应用程序属性来禁用默认过滤器:
zuul.SendErrorFilter.error.disable=true
然后通过扩展默认的 CustomSendErrorFilter 创建您自己的 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 中。