Jersey ContainerResponseFilter不适用于所有响应
问题描述:
我有一个Dropwizard 1.0.0应用程序,使用ContainerResponseFilter我希望看到一系列标题应用于每个资源 - 但我只看到它们应用于根级文档。Jersey ContainerResponseFilter不适用于所有响应
过滤器类:
package com.uk.jacob.filters;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.core.MultivaluedMap;
import java.io.IOException;
public class SecurityFilter implements ContainerResponseFilter {
@Override
public void filter(ContainerRequestContext containerRequestContext, ContainerResponseContext containerResponseContext) throws IOException {
MultivaluedMap<String, Object> headers = containerResponseContext.getHeaders();
headers.add("strict-transport-security", "max-age=31536000");
headers.add("x-content-type-options", "nosniff");
headers.add("x-frame-options", "SAMEORIGIN");
headers.add("x-xss-protection", "1; mode=block");
}
}
应用类:
package com.uk.jacob;
import com.uk.jacob.filters.SecurityFilter;
import com.uk.jacob.resources.HomepageResource;
import io.dropwizard.Application;
import io.dropwizard.assets.AssetsBundle;
import io.dropwizard.client.HttpClientBuilder;
import io.dropwizard.setup.Bootstrap;
import io.dropwizard.setup.Environment;
import io.dropwizard.views.ViewBundle;
import org.apache.http.client.HttpClient;
public class websiteApplication extends Application<websiteConfiguration> {
public static void main(final String[] args) throws Exception {
new websiteApplication().run(args);
}
@Override
public String getName() {
return "website";
}
@Override
public void initialize(final Bootstrap<websiteConfiguration> bootstrap) {
bootstrap.addBundle(new ViewBundle<websiteConfiguration>());
bootstrap.addBundle(new AssetsBundle("/public/", "/public"));
}
@Override
public void run(final websiteConfiguration configuration, final Environment environment) {
final HttpClient httpClient = new HttpClientBuilder(environment).using(configuration.getHttpClientConfiguration()).build(getName());
environment.jersey().register(new SecurityFilter());
environment.jersey().register(new HomepageResource(httpClient));
}
}
答
您的问题是AssetBundle。 AssetBundles是独立的servlet,它们不通过球衣生态系统。来源:
@Override
public void run(Environment environment) {
LOGGER.info("Registering AssetBundle with name: {} for path {}", assetsName, uriPath + '*');
environment.servlets().addServlet(assetsName, createServlet()).addMapping(uriPath + '*');
}
这就是为什么您的过滤器不在资产资源上调用。解决这个问题的方法是编写一个额外的ServletFilter(旧样式),用于过滤资产请求并在其中添加标题。
还为了你的头添加到您的资产包,你必须使用一个普通Servlet过滤器,并与DW注册它:
这里是我的ServletFilter中的代码:
public class ServletRequestFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("Asset filter");
HttpServletResponse httpServletResponse = ((HttpServletResponse) response);
httpServletResponse.addHeader("ARTUR", "test");
chain.doFilter(request, httpServletResponse);
}
@Override
public void destroy() {
}
}
这是再注册如下:
public class ViewApplication extends io.dropwizard.Application<Configuration>{
@Override
public void run(Configuration configuration, Environment environment) throws Exception {
environment.jersey().register(ViewResource.class);
environment.jersey().register(HeaderResponseFilter.class);
environment.servlets().addFilter("Custom-Filter-Name", new ServletRequestFilter()).addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), true, "/assets/*");
}
@Override
public void initialize(Bootstrap<Configuration> bootstrap) {
super.initialize(bootstrap);
bootstrap.addBundle(new ViewBundle<>());
bootstrap.addBundle(new AssetsBundle("/assets/", "/assets"));
}
public static void main(String[] args) throws Exception {
new ViewApplication().run("server", "/home/artur/dev/repo/sandbox/src/main/resources/config/test.yaml");
}
}
注:我在/assets/
注册为网址的资产包。在我的过滤器(仅过滤资产资源)的注册中也会注意到这一点。或者,你可以在所有通话中匹配它,并通过它过滤所有内容(这样你就可以摆脱我相信的球衣)。
最后的测试我的资源:
[email protected]:~/dev/repo/sandbox$ curl -v "http://localhost:9085/assets/test.txt"
* Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 9085 (#0)
> GET /assets/test.txt HTTP/1.1
> Host: localhost:9085
> User-Agent: curl/7.47.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Mon, 19 Sep 2016 15:07:13 GMT
< ARTUR: test
< Last-Modified: Mon, 19 Sep 2016 14:52:37 GMT
< ETag: "0d1ae97d61a8900c99abddb8741febaf"
< Content-Type: text/plain;charset=utf-8
< Vary: Accept-Encoding
< Content-Length: 11
<
asd
asd
* Connection #0 to host localhost left intact
注意我的自定义页眉ARTUR: test
问候,
阿图尔
什么是根级别的文件?请添加不添加标题时的示例(加上您期望看到的内容)。从你提供的信息来看,这应该是正常的。 – pandaadb
我运行了一个快速测试我的箱子1视图和资源和筛选器正确应用。 – pandaadb
/index.html将工作 /image.png不会。这可能与AssetsBundle有关吗? –