我正在使用Resteasy开发一个小型JAX-RS应用程序。我希望应用程序为Javascript和CSS文件等提供一些静态内容。我想利用webjars.org的jar中打包的资源的已经gzip压缩版本。因此,我需要处理Accept-Encoding
标头并检查.gz
是否存在。
到目前为止,我所拥有的是:
@Path("res/{path:.*}")
@GET
public Response webjars(@PathParam("path") String path, @HeaderParam("Accept-Encoding") String acceptEncoding) {
// Guesses MIME type from the path extension elsewhere.
String mime = mimes.getContentType(path);
if (acceptEncoding.contains("gzip")) {
InputStream is = getClass().getResourceAsStream("/META-INF/resources/webjars/" + path + ".gz");
if (is != null)
return Response.ok().type(mime).encoding("gzip").entity(is).build();
}
InputStream is = getClass().getResourceAsStream("/META-INF/resources/webjars/" + path);
if (is != null)
return Response.ok().type(mime).entity(is).build();
return Response.status(Status.NOT_FOUND).build();
}
但它不起作用。所提供的内容完全被打破。到目前为止,我发现了一个再次压缩流的组件:org.jboss.resteasy.plugins.interceptors.encoding.GZIPEncodingInterceptor,因为我手动填充了Content-Encoding
标头(使用ResponseBuilder.encoding
方法)。
这看起来像是一个错误,因为显然,没有办法共享已经gzipped的流。但是,使用JAX-RS可以实现吗?这是一个Resteasy错误吗?
我可以想到在Resteasy外部实现相同功能的各种方法,比如映射webjars.org servlet(我不在Servlet API 3.0环境中,所以我没有META-INF/resources/
自动类路径映射)。尽管如此,我的问题仍然存在。它适用于其他几种情况。
更新
我已填写问题RESTEASY-1170。
答案 0 :(得分:2)
以上是我上述评论的示例实现。
我要说的是,如果您不希望它被当前拦截器处理,请不要设置标头,创建一个名称绑定的拦截器,使用您自己的注释,并设置优先级低于您想要避免的优先级,然后在拦截器中设置标题...
@AlreadyGzipped
@NameBinding
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface AlreadyGzipped {}
WriterInterceptor
。请注意@Priority
。 GZIPEncodingInterceptor
使用Priorities.ENTITY_CODER
@Provider
@AlreadyGzipped
@Priority(Priorities.ENTITY_CODER + 1000)
public class AlreadyGzippedWriterInterceptor implements WriterInterceptor {
@Context HttpHeaders headers;
@Override
public void aroundWriteTo(WriterInterceptorContext wic) throws IOException,
WebApplicationException {
String header = headers.getHeaderString("Accept-Encoding");
if (null != header && header.equalsIgnoreCase("gzip")) {
wic.getHeaders().putSingle("Content-Encoding", "gzip");
}
wic.proceed();
}
}
测试资源
@Path("resource")
public class AlreadyGzippedResoure {
@GET
@AlreadyGzipped
@Produces(MediaType.APPLICATION_OCTET_STREAM)
public Response getAlreadGzipped() throws Exception {
InputStream is = getClass().getResourceAsStream("/stackoverflow.png.gz");
return Response.ok(is).build();
}
}
测试
public class Main {
public static void main(String[] args) throws Exception {
Client client = ClientBuilder.newClient();
String url = "http://localhost:8080/api/resource";
Response response = client.target(url).request().acceptEncoding("gzip").get();
Image image = ImageIO.read(response.readEntity(InputStream.class));
JOptionPane.showMessageDialog(null,new JLabel(new ImageIcon(image)));
}
}
结果