Я пытаюсь написать простое приложение Джерси, которое отправляет файлы с Джерси-клиентом на сервер Джерси и обратно. Однако файлы, по-видимому, кодируются на пути от клиента к серверу, но не наоборот. Интересно, как я могу изменить это поведение.
Я тестирую это в простом примере:
public class GZipEncodingTest extends JerseyTest {
private static final String PATH = "/";
private static final String QUESTION = "foo", ANSWER = "bar";
private static final String ENCODING_GZIP = "gzip";
@Path(PATH)
public static class MyResource {
@POST
public Response handle(String question) throws IOException {
assertEquals(QUESTION, question);
return Response.ok(ANSWER).build(); // (1)
}
}
@Override
protected Application configure() {
enable(TestProperties.LOG_TRAFFIC);
enable(TestProperties.DUMP_ENTITY);
return new ResourceConfig(MyResource.class, GZipEncoder.class);
}
@Override
@SuppressWarnings("unchecked")
protected void configureClient(ClientConfig config) {
config.register(new EncodingFeature(ENCODING_GZIP, GZipEncoder.class));
}
@Test
public void testHeaders() throws Exception {
Response response = target().path(PATH).request().post(Entity.text(QUESTION));
assertEquals(ANSWER, response.readEntity(String.class));
}
}
Из зарегистрированного дампа я могу сказать, что запрос имеет значение: кодировка содержимого сигнализируется в заголовке и применяется к телу сообщения запроса. Также установлено значение Accept-Encoding. Сервер понимает применяемое сжатие gzip и распаковывает тело сообщения запроса. Тем не менее, он игнорирует тот факт, что клиент принимает ответ gzipped и отправляет тело сообщения ответа несжатым.
Когда я добавляю encoding(ENCODING_GZIP)
в строке (1) в цепочке Response
-builder, я получаю результат, который я ищу. Однако я хочу применить кодировку только в том случае, если она была помечена как приемлемая в запросе. Кроме того, я хочу объединить это приложение, а не только для конкретных ответов.
Я могу, конечно, добавить такую функцию вручную с помощью WriterInterceptor
:
public class GZipWriterInterceptor implements WriterInterceptor {
@Override
public void aroundWriteTo(WriterInterceptorContext context)
throws IOException, WebApplicationException {
context.getHeaders().add(HttpHeaders.CONTENT_ENCODING, ENCODING_GZIP);
context.proceed();
}
}
но я убежден, что это ненужная плита котла.
EncodingFeature
кажется только частью клиентской библиотеки. Я в основном ищут возможность заставить сервер Джерси кодировать данные как gzip всякий раз, когда запрос предлагал кодирование посредством accept-encoding.
Когда я пытаюсь искать решения в Интернете, я нахожу много. Большинство из них относятся к Джерси 1. Некоторые из них предлагают добавить слушателя к GrizzlyServer (который был бы Джерси, а не JAX-RS?). Затем в дереве зависимостей Jersey 2 есть много классов, которые предлагают кодировку GZip:
-
org.glassfish.grizzly.http.GZipContentEncoding
-
org.glassfish.jersey.message.GZipEncoder
-
org.glassfish.grizzly.compression.zip.GZipEncoder
-
org.glassfish.grizzly.compression.zip.GZipDecoder
-
org.glassfish.grizzly.compression.zip.GZipFilter
Я обнаружил, что люди в Интернете предлагают использовать любой из них, хотя мне нравится думать, что org.glassfish.jersey
кажется правильным выбором, поскольку он является фактической зависимостью от Джерси. Не говорить о тех, которые находятся в связанных библиотеках ApacheConnector
. Я понятия не имею, какой из них я должен использовать.