问题描述
我正在用Resteasy开发一个小型的JAX-RS应用程序.我希望该应用程序为Javascript和CSS文件等提供一些静态内容,并且我想利用 webjars.org .因此,我需要处理Accept-Encoding
标头,并检查.gz
是否存在(或不存在).
I'm developing a small JAX-RS application with Resteasy. I wanted the application to serve some static content for Javascript and CSS files, etc. and I would like to take advantage of the already gzipped version of the resources packaged in the jars of webjars.org. Thus, I need to handle the Accept-Encoding
header and check if the .gz
is there (or not).
到目前为止,我所拥有的是:
So far, what I have is:
@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
方法).
But it doesn't work. The content served is totally broken. So far, I've found that a component that compresses the stream again: org.jboss.resteasy.plugins.interceptors.encoding.GZIPEncodingInterceptor because I manually filled the Content-Encoding
header (using the ResponseBuilder.encoding
method).
在我看来,这似乎是一个错误,因为显然,无法共享已经压缩的流.但是,使用JAX-RS是否可以实现?这是Resteasy的错误吗?
This looks like a bug to me because, apparently, there's no way to share an already gzipped stream. However, Is this achievable using JAX-RS? Is this a Resteasy bug?
我可以想到多种方法来在外部实现与Resteasy相同的功能,例如映射webjars.org servlet(我不在Servlet API 3.0环境中,因此我没有META-INF/resources/
自动类路径映射) .不过,我的问题仍然存在.它适用于其他几种情况.
I can think of a variety of ways to achieve the same thing externally to Resteasy, like mapping the webjars.org servlet (I'm not in a Servlet API 3.0 environment, so I have no META-INF/resources/
automatic classpath mapping). Nevertheless, my questions still prevail. It applies to several other scenarios.
更新:
为了记录,我已填写了以下问题: RESTEASY-1170 .
For the record I have filled the issue RESTEASY-1170.
推荐答案
以下是我上面评论的示例实现.
Here's an example implementation of my above comment.
@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)));
}
}
结果
这篇关于如何在JAX-RS中提供已经压缩的内容?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!