Перейти к основному содержимому

Как сжимать запросы с помощью шаблона Spring RestTemplate

· 3 мин. чтения

1. Введение

В этом кратком руководстве мы рассмотрим, как отправлять HTTP-запросы, содержащие сжатые данные.

Кроме того, мы рассмотрим, как настроить веб-приложение Spring для обработки сжатых запросов.

2. Отправка сжатых запросов

Во-первых, давайте создадим метод, который сжимает массив байтов. Это пригодится в ближайшее время:

public static byte[] compress(byte[] body) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (GZIPOutputStream gzipOutputStream = new GZIPOutputStream(baos)) {
gzipOutputStream.write(body);
}
return baos.toByteArray();
}

Далее нам нужно реализовать ClientHttpRequestInterceptor для изменения запроса. Обратите внимание, что мы оба отправим соответствующие заголовки сжатия HTTP, а также вызовем наш метод сжатия тела:

public ClientHttpResponse intercept(HttpRequest req, byte[] body, ClientHttpRequestExecution exec)
throws IOException {
HttpHeaders httpHeaders = req.getHeaders();
httpHeaders.add(HttpHeaders.CONTENT_ENCODING, "gzip");
httpHeaders.add(HttpHeaders.ACCEPT_ENCODING, "gzip");
return exec.execute(req, compress(body));
}

Наш перехватчик берет тело исходящего запроса и сжимает его в формате GZIP. В этом примере мы используем стандартный GZIPOutputStream Java, чтобы сделать всю работу за нас.

Кроме того, мы должны добавить соответствующие заголовки для кодирования данных. Это позволяет конечной точке назначения узнать, что она имеет дело с данными, сжатыми GZIP.

Наконец, мы добавляем перехватчик в наше определение RestTemplate :

@Bean
public RestTemplate getRestTemplate() {
RestTemplate restTemplate = new RestTemplate();
restTemplate.getInterceptors().add(new CompressingClientHttpRequestInterceptor());
return restTemplate;
}

3. Обработка сжатых запросов

По умолчанию большинство веб-серверов не понимают запросы, содержащие сжатые данные. Веб-приложения Spring ничем не отличаются. Поэтому нам нужно настроить их для обработки таких запросов.

В настоящее время только веб-серверы Jetty и Undertow обрабатывают тела запросов с данными в формате GZIP. Пожалуйста, ознакомьтесь с нашей статьей о конфигурации приложения Spring Boot , чтобы настроить веб-сервер Jetty или Undertow.

3.1. Веб-сервер Jetty

В этом примере мы настраиваем веб-сервер Jetty, добавляя Jetty GzipHandler . Этот обработчик Jetty создан для сжатия ответов и распаковки запросов.

Однако добавления веб-сервера Jetty недостаточно. Нам нужно установить для inflateBufferSize значение больше нуля, чтобы включить распаковку:

@Bean
public JettyServletWebServerFactory jettyServletWebServerFactory() {
JettyServletWebServerFactory factory = new JettyServletWebServerFactory();
factory.addServerCustomizers(server -> {
GzipHandler gzipHandler = new GzipHandler();
gzipHandler.setInflateBufferSize(1);
gzipHandler.setHandler(server.getHandler());

HandlerCollection handlerCollection = new HandlerCollection(gzipHandler);
server.setHandler(handlerCollection);
});
return factory;
}

3.2. Веб-сервер Undertow

Точно так же мы можем настроить веб-сервер Undertow для автоматической распаковки запросов для нас. В этом случае нам нужно добавить собственный RequestEncodingHandler .

Мы настраиваем обработчик кодирования для обработки исходных данных GZIP из запроса:

@Bean
public UndertowServletWebServerFactory undertowServletWebServerFactory() {
UndertowServletWebServerFactory factory = new UndertowServletWebServerFactory();
factory.addDeploymentInfoCustomizers((deploymentInfo) -> {
deploymentInfo.addInitialHandlerChainWrapper(handler -> new RequestEncodingHandler(handler)
.addEncoding("gzip", GzipStreamSourceConduit.WRAPPER));
});
return factory;
}

4. Вывод

И это все, что нам нужно сделать, чтобы сжатые запросы заработали!

В этом руководстве мы рассмотрели, как создать перехватчик для RestTemplate , который сжимает содержимое запроса. Кроме того, мы рассмотрели, как автоматически распаковывать эти запросы в наших веб-приложениях Spring.

Важно отметить, что мы должны отправлять сжатый контент только на веб-серверы, способные обрабатывать такие запросы .

Полный рабочий пример для веб-сервера Jetty закончен на GitHub .