уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.

Продолжаю разбираться с HTTP Client API в Delphi и, надо сказать, что пока все замечательно. Не могу сказать кто быстрее/шустрее — Synapse или HTTP Client API, так как пока эту сторону вопроса не изучал, однако, могу сказать, что новый фреймворк Delphi для работы с HTTP вполне удобный и, на мой взгляд, имеет полное право на жизнь. Сегодня я рассмотрю один из вопросов, касающихся этой библиотеки, а именно — использованием GZip в HTTP Client API.

Возможность получать от сервера сжатые данные позволяет нам значительно экономить трафик и ускорить работу с сервером, так как по Сети данные будут идти в сжатом виде, а уже на клиенте мы их можем распаковать и обработать как нам необходимо. Забегая немного вперед, могу сказать, что HTTP Client API позволяет распаковывать данные сжатые в GZip «на лету» и для этого нам не потребуется никаких сторонних библиотек Delphi — только те библиотеки и возможности, которые предоставляет нам Delphi 10.3 Rio «из коробки».Про GZip я рассказывал ещё в 2011 году, когда изучал возможности библиотеки Synapse. Напомню кратко, что должен знать разработчик при работе с GZip в HTTP.

Как работать с GZip в Delphi?

1. Чтобы попросить у сервера вернуть данные сжатые в GZip необходимо в запросе отправить заголовок:

Accept-Encoding: gzip,deflate

То есть, говоря терминами Delphi, нам необходимо определить свойство AcceptEncoding у компонента TNetHTTPClient, установив значение:

var NetHTTPClient1:TNetHTTPClient; 
begin
  NetHTTPClient1.AcceptEncoding:='gzip,deflate';
end;

или же определить это же свойство у компонента запроса TNetHTTPRequest:

var NetHTTPRequest:TNetHTTPRequest; 
begin
  NetHTTPRequest.AcceptEncoding:='gzip,deflate';
end;

2. После запроса данных сервер может вернуть данные сжатые в GZip, если он (сервер) поддерживает такую возможность.
При этом, сервер вам сообщит в заголовках каким образом сжаты данные, например, может прислать вам такой заголовок:

Content-Encoding: gzip

3. Соответственно, если данные пришли в сжатом виде, мы должны взять эти самые данные и каким-либо способом их распаковать. Например, в той же статье 2011 года я использовал стороннюю библиотеку «delphi zlib».

Вот тот минимальный «курс молодого бойца» при работе с GZip в Delphi. Теперь посмотрим как эта возможность реализована в HTTP Client API.

Работа с GZip в HTTP Client API

Разработчики HTTP Client API постарались сделать работу с GZip максимально прозрачной и простой для пользователя. Как я упомянул выше, распаковка GZip происходит автоматически и, всё, что нам остается сделать — это определить одно свойство у THTTPClient, если вы не используете компоненты или у TNetHTTPClient, если вы используете компоненты с вкладки «Net». Свойство это называется AutomaticDecompression и имеет следующее описание:

THTTPCompressionMethod = (Deflate, GZip, Brotli, Any);
  THTTPCompressionMethods = set of THTTPCompressionMethod;
 
property AutomaticDecompression: THTTPCompressionMethods
      read GetAutomaticDecompression write SetAutomaticDecompression
      default [];

Значение THTTPCompressionMethod.Any используется для того, чтобы указать клиенту автоматически распаковывать данные сжатые любым поддерживаемым методом. Таким образом, определив свойство AutomaticDecompression, например, так:

NetHTTPClient1.AutomaticDecompression:=[THTTPCompressionMethod.Any];

Мы можем не беспокоиться об анализе заголовков ответа — если сервер вернет заголовок «Content-Encoding: gzip» или аналогичный, указывающий на то, что данные сжаты, то в HTTP Client API эти данные будут автоматически распакованы.

Для распаковки данных используется стандартная библиотека Delphi System.Zlib.

Это то, что связано с хорошими новостями относительно работы с GZip в HTTP Client API.

Плохая новость для тех, кто использует Delphi версии до Delphi 10.2 Tokyo включительно:

Автоматическая распаковка GZip появилась только в Delphi 10.3 Rio Release 1

Новые возможности, включая и работу с GZip в HTTP Client API введены в работу с использованием class helper следующего вида:

TNetHTTPClientHelper = class helper for TNetHTTPClient
  private
    [....]
  public
    roperty AutomaticDecompression: THTTPCompressionMethods
      read GetAutomaticDecompression write SetAutomaticDecompression
      default [];
  end;

Также следует отметить следующее:

Несмотря на то, что в HTTP Client API заявлена поддержка алгоритма Brotli, автоматически данные не распаковываются

Пример работы с GZip в Delphi 10.3 Rio

В качестве примера я накидал вот такое простенькое приложение для работы с GZip в HTTP Client API:

В верхний Memo будут выводиться заголовки ответа сервера, а в нижний — контент полученной страницы.

Код обработчика события OnClick единственной кнопки в приложении такой:

var AResponse: IHTTPResponse;
    ADecompMethods: THTTPCompressionMethods;
    AHeader: TNetHeader;
begin
  ADecompMethods:=[];
  memContent.Lines.Clear;
  memHeaders.Lines.Clear;
  //устанавливаем заголовок Accept-Encoding
  NetHTTPClient1.AcceptEncoding:=edAcceptEncoding.Text;
  //настраиваем свойство автоматической распаковки данных
  if chGzip.Checked then
    ADecompMethods:=ADecompMethods+[THTTPCompressionMethod.GZip];
  if chDeflate.Checked then
    ADecompMethods:=ADecompMethods+[THTTPCompressionMethod.Deflate];
  if chBrotli.Checked then
    ADecompMethods:=ADecompMethods+[THTTPCompressionMethod.Brotli];
  if chAny.Checked then
    ADecompMethods:=ADecompMethods+[THTTPCompressionMethod.Any];
 
  NetHTTPClient1.AutomaticDecompression:=ADecompMethods;
  //отправляем запрос и получаем ответ
  AResponse:=NetHTTPClient1.Get(edURL.Text);
  //выводим контент страницы
  memContent.Lines.LoadFromStream(AResponse.ContentStream);
  //выводим заголовки
  for AHeader in AResponse.Headers do
    memHeaders.Lines.Add(AHeader.Name+': '+AHeader.Value)
end;

В качестве примера запросим у сервера данный сжатые одним из алгоритмов (gzip, deflate или brotli) и, при этом, не будем настраивать автоматическую распаковку. Результат работы программы представлен на рисунке ниже:

Как видно, сервер вернул данные сжатые алгоритмом Brotli. Даже, если настроить автоматическую распаковку этих данных, то ничего не произойдет. Смотрим результат работы с включенной опцией распаковки данных:

Однако, если мы запросим данные, сжатые GZip, то распаковка происходит нормально и мы автоматически получаем исходный код страницы блога webdelphi.ru:
Резюмируем:

  1. Работа с GZip в HTTP Client API построена достаточно прозрачно для конечного пользователя — не требуется установка дополнительных библиотек, анализ заголовков сервера и т.д. Достаточно указать серверу каким алгоритмом можно сжимать данные (заголовок ACCEPT-ENCODING) и указать в свойстве AutomaticDecompression необходимые значения.
  2. Не критичный (лично для меня), но, тем не менее, печальный момент — данные сжатые алгоритмом Brotli в настоящее время автоматически не распаковываются. Этот баг зафиксирован и, если есть желание, то можете за него проголосовать. Обновление 14/03/2019: баг-репорт закрыт с пометкой «Работает как ожидалось». Автоматическая распаковка Brotli в Windows не поддерживается в WinHTTP, эта возможность используется только под Linux
  3. Функция автоматической распаковки сжатых данных доступна пользователям Delphi 10.3 Rio Release 1.

Пример Delphi, рассмотренный в этой статье можно скачать со страницы «Исходники»

«Исходники» —> «Интернет и Сети» —>Прочие

Книжная полка

Описание Подробно рассматривается библиотека FM, позволяющая создавать полнофункциональное программное обеспечение для операционных систем Windows и OS X, а также для смартфонов и планшетных компьютеров, работающих под управлением Android и iOS
купить книгу delphi на ЛитРес
Описание: Рассмотрены практические вопросы по разработке клиент-серверных приложений в среде Delphi 7 и Delphi 2005 с использованием СУБД MS SQL Server 2000, InterBase и Firebird. Приведена информация о теории построения реляционных баз данных и языке SQL. Освещены вопросы эксплуатации и администрирования СУБД.
купить книгу delphi на ЛитРес
Описание: Рассмотрены малоосвещенные вопросы программирования в Delphi. Описаны методы интеграции VCL и API. Показаны внутренние механизмы VCL и приведены примеры вмешательства в эти механизмы. Рассмотрено использование сокетов в Delphi: различные режимы их работы, особенности для протоколов TCP и UDP и др.
купить книгу delphi на ЛитРес
5 1 голос
Рейтинг статьи
уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.
Подписаться
Уведомить о
3 Комментарий
Межтекстовые Отзывы
Посмотреть все комментарии
KeeperWorld
KeeperWorld
18/03/2019 05:41

Проверил под Windows. Работает на ура! Автор — спасибо!!!
На радостях собрал проект под Android — увы: данные приходят в приложение в упакованном виде… :(
И как их теперь на Андроиде распаковать?
По умолчанию сделал так:
FHTTPClient := THTTPClient.Create;
FHTTPClient.AcceptEncoding := ‘gzip,deflate’;
FHTTPClient.AutomaticDecompression := [THTTPCompressionMethod.GZip];

Под Windows — всё ок, но Андрюша — расстроил…
Как починить? Надо задеплоить какую-нибудь системную библиотеку gzip.so?

PS. Заранее спасибо за помощь!

brunnengi
brunnengi
19/02/2020 22:29

HTTPClient получается скачивает данные сжатые.
А как отправить данные в формате GZip с помощью NetHTTPClient?