Продолжаю разбираться с 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 в HTTP Client API введены в работу с использованием class helper следующего вида:
TNetHTTPClientHelper = class helper for TNetHTTPClient private [....] public roperty AutomaticDecompression: THTTPCompressionMethods read GetAutomaticDecompression write SetAutomaticDecompression default []; end;
Также следует отметить следующее:
Пример работы с 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:
Резюмируем:
- Работа с GZip в HTTP Client API построена достаточно прозрачно для конечного пользователя — не требуется установка дополнительных библиотек, анализ заголовков сервера и т.д. Достаточно указать серверу каким алгоритмом можно сжимать данные (заголовок ACCEPT-ENCODING) и указать в свойстве AutomaticDecompression необходимые значения.
- Не критичный (лично для меня), но, тем не менее, печальный момент — данные сжатые алгоритмом Brotli в настоящее время автоматически не распаковываются. Этот баг зафиксирован и, если есть желание, то можете за него проголосовать. Обновление 14/03/2019: баг-репорт закрыт с пометкой «Работает как ожидалось». Автоматическая распаковка Brotli в Windows не поддерживается в WinHTTP, эта возможность используется только под Linux
- Функция автоматической распаковки сжатых данных доступна пользователям Delphi 10.3 Rio Release 1.
Пример Delphi, рассмотренный в этой статье можно скачать со страницы «Исходники»
Книжная полка
Описание Подробно рассматривается библиотека FM, позволяющая создавать полнофункциональное программное обеспечение для операционных систем Windows и OS X, а также для смартфонов и планшетных компьютеров, работающих под управлением Android и iOS
|
||
Описание: Рассмотрены практические вопросы по разработке клиент-серверных приложений в среде Delphi 7 и Delphi 2005 с использованием СУБД MS SQL Server 2000, InterBase и Firebird. Приведена информация о теории построения реляционных баз данных и языке SQL. Освещены вопросы эксплуатации и администрирования СУБД.
|
||
Название: О чем не пишут в книгах по Delphi
Описание: Рассмотрены малоосвещенные вопросы программирования в Delphi. Описаны методы интеграции VCL и API. Показаны внутренние механизмы VCL и приведены примеры вмешательства в эти механизмы. Рассмотрено использование сокетов в Delphi: различные режимы их работы, особенности для протоколов TCP и UDP и др.
|
Проверил под Windows. Работает на ура! Автор — спасибо!!!
На радостях собрал проект под Android — увы: данные приходят в приложение в упакованном виде… :(
И как их теперь на Андроиде распаковать?
По умолчанию сделал так:
FHTTPClient := THTTPClient.Create;
FHTTPClient.AcceptEncoding := ‘gzip,deflate’;
FHTTPClient.AutomaticDecompression := [THTTPCompressionMethod.GZip];
Под Windows — всё ок, но Андрюша — расстроил…
Как починить? Надо задеплоить какую-нибудь системную библиотеку gzip.so?
PS. Заранее спасибо за помощь!
По идее, под Андроид распаковка должна быть автоматической. Не пробовали в заголовках указывать не «gzip,deflate», а только «gzip»?
HTTPClient получается скачивает данные сжатые.
А как отправить данные в формате GZip с помощью NetHTTPClient?