如何在JAX-RS中提供已经压缩的内容? [英] How to serve already gzipped content in JAX-RS?

查看:122
本文介绍了如何在JAX-RS中提供已经压缩的内容?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用Resteasy开发一个小型的JAX-RS应用程序.我希望该应用程序为Javascript和CSS文件等提供一些静态内容,并且我想利用

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();
}

但是它不起作用.所提供的内容已完全损坏.到目前为止,我发现有一个再次压缩流的组件:

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.

我要说的是,如果您不希望它被当前的拦截器处理,请不要设置标头,创建一个将与您自己的注释进行名称绑定的拦截器,并设置将优先级设置为比您要避免的优先级低,然后在拦截器中设置标头...

The point I'm getting at is that if you don't want it to be handle by the current interceptor, don't set the header, create an Interceptor that will be name binded, with your own annotation, and set the priority to one lower than the one you want to avoid, then set the header in your Interceptor...

@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中提供已经压缩的内容?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆