Я хочу сжать тело ответа в javax.servlet.Filter.Вот мой код
byte[] bytes = // compressing response body
response.addHeader("Content-Encoding", "gzip");
response.addHeader("Content-Length", String.valueOf(bytes.length));
response.setContentLength(bytes.length);
response.setBufferSize(bytes.length * 2);
ServletOutputStream output = response.getOutputStream();
output.write(bytes);
output.flush();
output.close();
Но фактический ответ, который я вижу в Chrome Dev Tool:
Accept-Ranges: bytes
Cache-Control: max-age=2592000
Content-Type: application/javascript;charset=UTF-8
Date: Fri, 14 Dec 2018 15:34:25 GMT
Last-Modified: Tue, 09 Oct 2018 13:42:54 GMT
Server: Apache-Coyote/1.1
Transfer-Encoding: chunked
Я не ожидаю Transfer-Encoding: chunked, потому что я объявляю "Content-Length",Я написал простой тест на java
URLConnection connection = new URL("http://127.0.0.1:8081/js/ads.js").openConnection();
connection.addRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8");
connection.addRequestProperty("Accept-Encoding", "gzip, deflate");
connection.addRequestProperty("Accept-Language", "ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7");
connection.addRequestProperty("Cache-Control", "no-cache");
connection.addRequestProperty("Connection", "keep-alive");
connection.addRequestProperty("Host", "127.0.0.1:8081");
connection.addRequestProperty("Pragma", "no-cache");
connection.addRequestProperty("Upgrade-Insecure-Requests", "1");
connection.addRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36");
connection.connect();
connection.getHeaderFields().forEach((s, strings) ->
System.out.println(s + ":" + String.join(",", strings)));
, и вот что я нашел:
- , если я прокомментирую настройку заголовка «Пользователь-агент» или изменит «Пользователь-агент» налюбое другое значение, тогда я получаю ответ с «Content-Length»
- , если «User-Agent» указывает на Chrome, тогда я получаю Transfer-Encoding: chunked.
Я отлажен доsun.nio.ch.SocketChannel # write метод, и он получает правильные ByteBuffers со значениями заголовка Content-Length.
Не могу понять, где происходит эта магическая трансформация на куски?
Обновление
Странно то, что я записываю сжатые байты в Socket (я уверен, что я отлажен до вызова записи собственного метода в реализации SocketChannel).Но URLConnection возвращает мой распакованный байтовый массив с пользовательским агентом Chrome и правильный gziped байтовый массив, если я не укажу заголовок User-Agent или не добавлю какую-нибудь случайную строку.Похоже, что волшебство происходит где-то в реализации сокета Windows.