Jetty 和 Dropwizard:如何 return 总是 200 而不是 404、500 等
Jetty and Dropwizard: how to return always 200 instead of 404, 500, etc
我正在使用 Jetty-Jersey-Jackson 堆栈附带的 Dropwizard 0.8.0。
出于安全原因,我想添加一个过滤器,使每个通过 Jersey returns 定义的特定路由的请求始终为 200,即使出现错误(4xx、5xx 等)也是如此。
Jetty/Servlet 过滤器是否可行?我可以拦截请求 在 它通过 Jersey 资源(控制器),但在返回给客户端之前,以修改 http 状态代码吗?
更新:
我正在尝试使用 ServletFilter 执行此操作,但似乎在执行我的代码之前将响应发送到客户端。
我是这样写过滤器的:
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
{
if (response instanceof HttpServletResponse) {
/* No pre-processing */
chain.doFilter(request, response);
/* Post-processing: */
HttpServletResponse modifiedResponse = (HttpServletResponse) response;
if (modifiedResponse.getStatus() != 200) {
modifiedResponse.setStatus(200);
}
}
}
有了这个,在 Dropwizard 中注册了:
environment.servlets().addFilter("MyCustomFilter", new MyCustomFilter())
.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), true, "/mypath/*");
过滤器被执行,在 access.log 我看到所有状态码为 200 的请求;但客户端总是得到 "real" 状态码(例如,404 或 "Method not allowed")。
似乎在执行过滤器的最后一部分之前将响应发送到客户端。而且,我无法修改响应正文。我也尝试使用 HttpServletResponseWrapper,但没有成功。
您可以创建自定义 javax.ws.rs.ext.ExceptionMapper<RuntimeException>
。在那种情况下,您从服务器获得的每个异常,都可以将其解析为 200。
检查此 guy。它应该很容易与您需要的东西集成。
而不是教程向您展示的内容,就像这个例子:
if (webAppException.getResponse().getStatus() == 401) {
return Response
.status(Response.Status.UNAUTHORIZED)
.entity(new PublicFreemarkerView("error/401.ftl"))
.build();
}
您的代码将是
if (webAppException.getResponse().getStatus() == 401) {
return Response
.status(Response.Status.OK)
.build();
}
我正在用最终有效的解决方案更新问题:我使用了 Jersey 过滤器而不是 Jetty http 过滤,以便直接管理来自 Jersey 的 Response 对象。
显然,这仅在您使用 Jetty+Jersey 时有效,而不是独立 Jetty。
这是我正在使用的过滤器:
/**
* When active, this filter transforms all responses for specified basePath to 200, even in case of error.
*/
@Provider
public class DiscardErrors implements ContainerResponseFilter
{
private String basePath;
public DiscardErrors(String basePath)
{
this.basePath = basePath;
}
@Override
public void filter(ContainerRequestContext containerRequestContext, ContainerResponseContext containerResponseContext) throws IOException
{
if containerRequestContext.getUriInfo().getPath().startsWith(this.basePath) {
if (containerResponseContext.getStatus() != 200) { // Check if response code is different from 200
containerResponseContext.setStatus(200); // Force 200 status code
containerResponseContext.setEntity(""); // Empty body
}
}
}
}
并在 Dropwizard 中注册:
environment.jersey().register(new DiscardErrors("/"));
我正在使用 Jetty-Jersey-Jackson 堆栈附带的 Dropwizard 0.8.0。
出于安全原因,我想添加一个过滤器,使每个通过 Jersey returns 定义的特定路由的请求始终为 200,即使出现错误(4xx、5xx 等)也是如此。
Jetty/Servlet 过滤器是否可行?我可以拦截请求 在 它通过 Jersey 资源(控制器),但在返回给客户端之前,以修改 http 状态代码吗?
更新:
我正在尝试使用 ServletFilter 执行此操作,但似乎在执行我的代码之前将响应发送到客户端。
我是这样写过滤器的:
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
{
if (response instanceof HttpServletResponse) {
/* No pre-processing */
chain.doFilter(request, response);
/* Post-processing: */
HttpServletResponse modifiedResponse = (HttpServletResponse) response;
if (modifiedResponse.getStatus() != 200) {
modifiedResponse.setStatus(200);
}
}
}
有了这个,在 Dropwizard 中注册了:
environment.servlets().addFilter("MyCustomFilter", new MyCustomFilter())
.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), true, "/mypath/*");
过滤器被执行,在 access.log 我看到所有状态码为 200 的请求;但客户端总是得到 "real" 状态码(例如,404 或 "Method not allowed")。
似乎在执行过滤器的最后一部分之前将响应发送到客户端。而且,我无法修改响应正文。我也尝试使用 HttpServletResponseWrapper,但没有成功。
您可以创建自定义 javax.ws.rs.ext.ExceptionMapper<RuntimeException>
。在那种情况下,您从服务器获得的每个异常,都可以将其解析为 200。
检查此 guy。它应该很容易与您需要的东西集成。
而不是教程向您展示的内容,就像这个例子:
if (webAppException.getResponse().getStatus() == 401) {
return Response
.status(Response.Status.UNAUTHORIZED)
.entity(new PublicFreemarkerView("error/401.ftl"))
.build();
}
您的代码将是
if (webAppException.getResponse().getStatus() == 401) {
return Response
.status(Response.Status.OK)
.build();
}
我正在用最终有效的解决方案更新问题:我使用了 Jersey 过滤器而不是 Jetty http 过滤,以便直接管理来自 Jersey 的 Response 对象。
显然,这仅在您使用 Jetty+Jersey 时有效,而不是独立 Jetty。
这是我正在使用的过滤器:
/**
* When active, this filter transforms all responses for specified basePath to 200, even in case of error.
*/
@Provider
public class DiscardErrors implements ContainerResponseFilter
{
private String basePath;
public DiscardErrors(String basePath)
{
this.basePath = basePath;
}
@Override
public void filter(ContainerRequestContext containerRequestContext, ContainerResponseContext containerResponseContext) throws IOException
{
if containerRequestContext.getUriInfo().getPath().startsWith(this.basePath) {
if (containerResponseContext.getStatus() != 200) { // Check if response code is different from 200
containerResponseContext.setStatus(200); // Force 200 status code
containerResponseContext.setEntity(""); // Empty body
}
}
}
}
并在 Dropwizard 中注册:
environment.jersey().register(new DiscardErrors("/"));