如何使用Spring RestTemplate压缩HTTP请求?

Bartosz Bilicki:

如何gzip HTTP 请求,由创建org.springframework.web.client.RestTemplate?

我正在使用Spring 4.2.6Spring Boot 1.3.5(Java SE,而不是Web浏览器中的Android或Javascript)。

我正在提出一些非常大的POST请求,并且我希望压缩请求正文

德斯蒂尼文字:

我提出了两种解决方案,一种更简单,无需流传输,另一种支持流传输。

如果您不需要流媒体,请使用custom ClientHttpRequestInterceptor,一个Spring功能。

RestTemplate rt = new RestTemplate();
rt.setInterceptors(Collections.singletonList(interceptor));

interceptor可能在哪里

ClientHttpRequestInterceptor interceptor = new ClientHttpRequestInterceptor() {

    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
            throws IOException {
        request.getHeaders().add("Content-Encoding", "gzip");
        byte[] gzipped = getGzip(body);
        return execution.execute(request, gzipped);
    } 
 }

getGzip复制了

    private byte[] getGzip(byte[] body) throws IOException {

        ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
        try {
            GZIPOutputStream zipStream = new GZIPOutputStream(byteStream);
            try {
                zipStream.write(body);
            } finally {
                zipStream.close();
            }
        } finally {
            byteStream.close();
        }

        byte[] compressedData = byteStream.toByteArray();
        return compressedData;

    }

配置拦截器后,所有请求将被压缩。

这种方法的缺点是它不支持流式传输,因为ClientHttpRequestInterceptor将内容作为byte[]

如果您需要流式传输,请创建一个custom ClientHttpRequestFactory,说出来GZipClientHttpRequestFactory,然后像这样使用它:

    SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
    requestFactory.setBufferRequestBody(false);
    ClientHttpRequestFactory gzipRequestFactory = new GZipClientHttpRequestFactory(requestFactory);
    RestTemplate rt = new RestTemplate(gzipRequestFactory);

在哪里GZipClientHttpRequestFactory

public class GZipClientHttpRequestFactory extends AbstractClientHttpRequestFactoryWrapper {

    public GZipClientHttpRequestFactory(ClientHttpRequestFactory requestFactory) {
        super(requestFactory);
    }

    @Override
    protected ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod, ClientHttpRequestFactory requestFactory)
            throws IOException {
        ClientHttpRequest delegate = requestFactory.createRequest(uri, httpMethod);
        return new ZippedClientHttpRequest(delegate);
    }

}

并且ZippedClientHttpRequest是:

public class ZippedClientHttpRequest extends WrapperClientHttpRequest
{
    private GZIPOutputStream zip;

    public ZippedClientHttpRequest(ClientHttpRequest delegate) {
        super(delegate);
        delegate.getHeaders().add("Content-Encoding", "gzip");
        // here or in getBody could add content-length to avoid chunking
        // but is it available ? 
        // delegate.getHeaders().add("Content-Length", "39");

    }

    @Override
    public OutputStream getBody() throws IOException {
        final OutputStream body = super.getBody();
        zip = new GZIPOutputStream(body);
        return zip;
    }

    @Override
    public ClientHttpResponse execute() throws IOException {
        if (zip!=null) zip.close();
        return super.execute();
    }

}

最后WrapperClientHttpRequest是:

public class WrapperClientHttpRequest implements ClientHttpRequest {

    private final ClientHttpRequest delegate;

    protected WrapperClientHttpRequest(ClientHttpRequest delegate) {
        super();
        if (delegate==null)
            throw new IllegalArgumentException("null delegate");
        this.delegate = delegate;
    }

    protected final ClientHttpRequest getDelegate() {
        return delegate;
    }

    @Override
    public OutputStream getBody() throws IOException {
        return delegate.getBody();
    }

    @Override
    public HttpHeaders getHeaders() {
        return delegate.getHeaders();
    }

    @Override
    public URI getURI() {
        return delegate.getURI();
    }

    @Override
    public HttpMethod getMethod() {
        return delegate.getMethod();
    }

    @Override
    public ClientHttpResponse execute() throws IOException {
        return delegate.execute();
    }
}

这种方法使用分块传输编码创建请求,如果知道大小,则可以设置内容长度标头来更改此请求

ClientHttpRequestInterceptor和/或自定义ClientHttpRequestFactory方法的优点是它可以与RestTemplate的任何方法一起使用。另一种方法,传递一个RequestCallback能够仅与execute方法,这是因为RestTemplate的其它方法在内部创建他们自己的RequestCallback(S)产生的内容。

顺便说一句,似乎几乎没有支持在服务器上解压缩gzip请求还相关:在WebRequest中发送压缩数据?指出了Zip Bomb问题。我认为您将不得不为此编写一些代码

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

测量Spring RestTemplate HTTP请求时间

使用Resttemplate多个异步HTTP请求

如何配置spring的RestTemplate发出http2请求?

使用Spring RestTemplate通过特定的网络接口发送HTTP请求

如何使用 Java Spring 的 RestTemplate 的交换方法向 HTTP 请求添加正文?

Spring RestTemplate HTTP Post与参数导致400错误的请求错误

如何使用Spring RestTemplate发送XML POST请求?

如何使用spring RestTemplate针对Cloudant API发出测试请求?

(转到)发送HTTP请求时如何控制gzip压缩?

如何在Go中GZIP压缩http请求?

如何在Spring RestTemplate中将HTTP标头传递给GET请求

如何通过Spring RestTemplate更改获取请求中的响应http标头?

我可以使用GZIP压缩HTTP请求吗?

如何将带有 HTTP 基本身份验证的 curl 请求转换为 Spring RestTemplate 请求?

使用Spring Android RestTemplate发送Gzip压缩数据?

使用spring resttemplate向每个请求添加请求参数

使用RestTemplate Http获取请求-org.springframework.web.client.ResourceAccessException

java.net.SocketException:使用RestTemplate发送HTTP请求时重置连接

如何使用Spring MVC正确记录HTTP请求

Spring WS请求GZIP压缩

如何使用Struts 2压缩ajax请求?

如何使用WebClient压缩JSON请求正文?

我应该如何指示我的HTTP服务器支持压缩请求?

如何恢复下载使用Spring RestTemplate?

如何使用 Spring RestTemplate 获取 JSON 对象?

如何使用 spring RestTemplate 发送 multipartFile?

如何在Spring RestTemplate请求上设置“ Accept:”标头?

如何在Spring MVC中解码Gzip压缩的请求主体

卷曲令牌请求到Spring RestTemplate转换