2016-09-08 4 views
2

Я включил сжатие gzip для всех ответов в моей веб-службе (Play 2.4), следуя those instructions. Легко настроить, и я вижу, что это работает как шарм, проверивший с помощью curl и wirehark, что ответы отправляются сжатыми.Play WS - проверьте заголовки сжатия

Теперь я хочу быть хорошим разработчиком и добавить интеграционный тест, чтобы никто не нарушил HTTP-сжатие на следующей неделе. Вот где начинается самое интересное! Мой тест выглядит следующим образом:

"use HTTP compression" in { 
    forAll(endPoints) { endPoint => 
    val response = await(
     WS.url(Localhost + port + "/api" + endPoint).withHeaders("Accept-Encoding" -> "gzip").get() 
    ) 
    response.header("Content-Encoding") mustBe Some("gzip") 
    } 
} 

Однако, тест не пройден, как заголовки ответа WS не включают в себя содержание enconding информации, а тело возвращается в виде обычного текста, несжатый.

[info] - should use HTTP compression *** FAILED *** 
[info] forAll failed, because: 
[info]  at index 0, None was not equal to Some("gzip") (ApplicationSpec.scala:566) 

Проверка трафика в Wireshark при выполнении этого теста я могу ясно видеть, что сервер возвращает GZIP закодированного ответ, поэтому он выглядит как-то WS прозрачна распаковкой ответа и обнажая заголовки Content-Encoding? Есть ли способ получить простой, сжатый ответ с полными заголовками, чтобы я мог проверить, сжат ли ответ или нет?

+0

У вас есть решение для этого? – Salem

+0

См. Мой ответ [ниже] (http://stackoverflow.com/a/39701208/887422) (он оказался слишком большим для ответа только на комментарий). Я закончил тем, что использовал простые старые классы Java и вообще обошел Play-WS для этого единственного теста, потому что мне нужно было что-то более низкоуровневое. – jjst

ответ

1

Я не думаю, что вы можете это сделать. Если я не ошибаюсь, проблема в том, что Netty возвращает уже несжатый контент, поэтому заголовок также удаляется.

В AsyncHTTPClient есть конфигурация, чтобы установить это (setKeepEncoding), но, к сожалению, это работает только в версии 2.0 и новее, а Play 2.4 WS lib использует версию 1.9.x.

В любом случае, клиент Play дает вам уже настроенную настройку, и я не знаю, можете ли вы ее настроить. Но вы можете создать нового клиента, чтобы подражать этому поведению:

// Converted from Java code: I have never worked with those APi's in Scala 
val cfg = new AsyncHttpClientConfig.Builder().addResponseFilter(new ResponseFilter { 
     override def filter[T](ctx: FilterContext[T]): FilterContext[T] = { 
      val headers = ctx.getRequest.getHeaders 
      if (headers.containsKey("Accepts-Encoding")) { 
       ctx.getResponseHeaders.getHeaders.put("Content-Encoding", List("gzip")) 
      } 
      ctx 
     } 
    }).build() 
val client: NingWSClient = NingWSClient(cfg) 
client.url("...") // (...) 

Опять же, это просто эмулирует нужный результат. Кроме того, возможно, более умная логика, чем просто добавить gzip как Content-Encoding (например: поместить первый алгоритм, запрошенный в «Accepts Encoding»).

+0

заголовок называется «Accept-Encoding» –

1

Оказывается, мы не можем использовать Play-WS для этого конкретного теста, потому что он уже возвращает содержимое без сжатия и лишено заголовка (см. Проницательный ответ @ Salem), поэтому нет возможности проверить, сжат ли ответ ,

Однако достаточно просто написать тест, который проверяет HTTP-сжатие с использованием стандартных классов Java. Все, о чем мы заботимся, заключается в том, отвечает ли сервер в (действительной) форме GZIP при отправке запроса с Accept-Encoding: gzip. Вот что у меня получилось:

forAll(endPoints) { endPoint => 
    val url = new URL(Localhost + port + "/api/" + endPoint) 
    val connection = url.openConnection().asInstanceOf[HttpURLConnection] 
    connection.setRequestProperty("Accept-Encoding", "gzip") 
    Try { 
     new GZIPInputStream(connection.getInputStream) 
    } must be a 'success 
    } 
Смежные вопросы