diff --git a/README.md b/README.md index 551637f..1a80887 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ - Отправка данных формы (полей формы), `application/x-www-form-urlencoded` - Отправка данных формы (полей формы и файлов), `multipart/form-data` - Прозрачная поддержка ответов, закодированных `GZip` +- Сжатие тела запроса `GZip` - `Basic`, `Digest` и `AWS4-HMAC-SHA256` аутентификация - Автоматическое разрешение редиректов - Установка и чтение Cookies @@ -221,8 +222,27 @@ XML = Результат = КоннекторHTTP.КакДвоичныеДанные(КоннекторHTTP.Get("http://httpbin.org/image/png")); ``` -## GZip-декодирование +## GZip-кодирование тела запроса +**Коннектор** может автоматически сжимать тело запроса `GZip`. +Для этого нужно добавить заголовок `Content-Encoding` = `gzip`. + +**Примечание**: сервер должен быть настроен соответствующим образом, чтобы распаковывать входящие запросы. + +```bsl +Json = Новый Структура; +Json.Вставить("field", "value"); +Json.Вставить("field2", "value2"); +Заголовки = Новый Соответствие; +Заголовки.Вставить("Content-Encoding", "gzip"); +Результат = КоннекторHTTP.PostJson("http://httpbin.org/anything", Json, Новый Структура("Заголовки", Заголовки)); +``` + +## GZip-декодирование тела ответа По умолчанию **Коннектор** просит сервер кодировать ответы в формате `GZip`. + +**Примечание**: любое кодирование тела ответа можно отключить, задав заголовок +`Accept-Encoding` = `identity`. + Декодирование выполняется прозрачным образом в методах `GetJson`, `PostJson`, `PutJson`, `DeleteJson`, `КакJson`, `КакТекст`, `КакДвоичныеДанные`. ```bsl Результат = КоннекторHTTP.GetJson("http://httpbin.org/gzip"); diff --git a/src/CommonModules/КоннекторHTTP/Ext/Module.bsl b/src/CommonModules/КоннекторHTTP/Ext/Module.bsl index d97bfe5..4fa0786 100644 --- a/src/CommonModules/КоннекторHTTP/Ext/Module.bsl +++ b/src/CommonModules/КоннекторHTTP/Ext/Module.bsl @@ -17,7 +17,7 @@ // // URL: https://github.com/vbondarevsky/Connector // e-mail: vbondarevsky@gmail.com -// Версия: 1.4.0 +// Версия: 1.4.1 // // Требования: платформа 1С версии 8.3.10 и выше @@ -36,7 +36,7 @@ // ДополнительныеПараметры - Структура - см. описание параметра в ВызватьМетодВСеансе. // // Возвращаемое значение: -// Структура - ответ на выполненный запрос. См. описание возвращаемого значения в ВызватьМетодВСеансе. +// Структура - ответ на выполненный запрос. См. описание возвращаемого значения в ВызватьМетодВСеансе. // Функция Get(URL, ПараметрыЗапроса = Неопределено, ДополнительныеПараметры = Неопределено) Экспорт @@ -53,7 +53,7 @@ // ДополнительныеПараметры - Структура - см. описание параметра в ВызватьМетодВСеансе. // // Возвращаемое значение: -// Структура - ответ на выполненный запрос. См. описание возвращаемого значения в ВызватьМетодВСеансе. +// Структура - ответ на выполненный запрос. См. описание возвращаемого значения в ВызватьМетодВСеансе. // Функция Options(URL, ДополнительныеПараметры = Неопределено) Экспорт @@ -70,7 +70,7 @@ // ДополнительныеПараметры - Структура - см. описание параметра в ВызватьМетодВСеансе. // // Возвращаемое значение: -// Структура - ответ на выполненный запрос. См. описание возвращаемого значения в ВызватьМетодВСеансе. +// Структура - ответ на выполненный запрос. См. описание возвращаемого значения в ВызватьМетодВСеансе. // Функция Head(URL, ДополнительныеПараметры = Неопределено) Экспорт @@ -88,7 +88,7 @@ // ДополнительныеПараметры - Структура - см. описание параметра в ВызватьМетодВСеансе. // // Возвращаемое значение: -// Структура - ответ на выполненный запрос. См. описание возвращаемого значения в ВызватьМетодВСеансе. +// Структура - ответ на выполненный запрос. См. описание возвращаемого значения в ВызватьМетодВСеансе. // Функция Post(URL, Данные = Неопределено, ДополнительныеПараметры = Неопределено) Экспорт @@ -124,7 +124,7 @@ // ДополнительныеПараметры - Структура - см. описание параметра в ВызватьМетодВСеансе. // // Возвращаемое значение: -// Структура - ответ на выполненный запрос. См. описание возвращаемого значения в ВызватьМетодВСеансе. +// Структура - ответ на выполненный запрос. См. описание возвращаемого значения в ВызватьМетодВСеансе. // Функция Patch(URL, Данные = Неопределено, ДополнительныеПараметры = Неопределено) Экспорт @@ -142,7 +142,7 @@ // ДополнительныеПараметры - Структура - см. описание параметра в ВызватьМетодВСеансе. // // Возвращаемое значение: -// Структура - ответ на выполненный запрос. См. описание возвращаемого значения в ВызватьМетодВСеансе. +// Структура - ответ на выполненный запрос. См. описание возвращаемого значения в ВызватьМетодВСеансе. // Функция Delete(URL, Данные = Неопределено, ДополнительныеПараметры = Неопределено) Экспорт @@ -247,7 +247,7 @@ // ДополнительныеПараметры - Структура - см. описание параметра в ВызватьМетодВСеансе. // // Возвращаемое значение: -// Структура - ответ на выполненный запрос. См. описание возвращаемого значения в ВызватьМетодВСеансе. +// Структура - ответ на выполненный запрос. См. описание возвращаемого значения в ВызватьМетодВСеансе. // Функция ВызватьМетод(Метод, URL, ДополнительныеПараметры = Неопределено) Экспорт @@ -296,7 +296,7 @@ // Строка - ответ сервера в виде текста. // Функция КакТекст(Ответ, Кодировка = Неопределено) Экспорт - + Если Не ЗначениеЗаполнено(Кодировка) Тогда Кодировка = Ответ.Кодировка; КонецЕсли; @@ -324,7 +324,7 @@ // Функция КакДвоичныеДанные(Ответ) Экспорт - Возврат РаспаковатьОтвет(Ответ); + Возврат РаспаковатьОтвет(Ответ); КонецФункции @@ -755,13 +755,13 @@ ЧтениеДанных.КопироватьВ(ЗаписьДанных, РазмерСжатыхДанных); ЗаписьДанных.Закрыть(); - ЗаписьДанных = Новый ЗаписьДанных(ПотокZip); + ЗаписьДанных = Новый ЗаписьДанных(ПотокZip); CRC32 = ЧтениеДанных.ПрочитатьЦелое32(); РазмерНесжатыхДанных = ЧтениеДанных.ПрочитатьЦелое32(); ЧтениеДанных.Закрыть(); - ЗаписьДанных.ЗаписатьБуферДвоичныхДанных(ZipDD(CRC32, РазмерСжатыхДанных, РазмерНесжатыхДанных)); + ЗаписьДанных.ЗаписатьБуферДвоичныхДанных(ZipDD(CRC32, РазмерСжатыхДанных, РазмерНесжатыхДанных)); ЗаписьДанных.ЗаписатьБуферДвоичныхДанных(ZipCDH(CRC32, РазмерСжатыхДанных, РазмерНесжатыхДанных)); ЗаписьДанных.ЗаписатьБуферДвоичныхДанных(ZipEOCD(РазмерСжатыхДанных)); ЗаписьДанных.Закрыть(); @@ -1295,6 +1295,9 @@ КонецЕсли; HTTPЗапрос.Заголовки = ПодготовленныйЗапрос.Заголовки; + + УпаковатьЗапрос(HTTPЗапрос); + ПодготовленныйЗапрос.Вставить("HTTPЗапрос", HTTPЗапрос); КонецПроцедуры @@ -1305,7 +1308,7 @@ Если Не ЗначениеЗаполнено(ПодготовленныйЗапрос.Аутентификация) Тогда СтруктураURL = РазобратьURL(ПодготовленныйЗапрос.URL); Если ЗначениеЗаполнено(СтруктураURL.Аутентификация) Тогда - ПодготовленныйЗапрос.Аутентификация = СтруктураURL.Аутентификация; + ПодготовленныйЗапрос.Аутентификация = СтруктураURL.Аутентификация; КонецЕсли; КонецЕсли; @@ -1499,7 +1502,7 @@ КонецЕсли; КонецЦикла; КонецЕсли; - КонецЦикла; + КонецЦикла; Возврат Cookies; @@ -2501,6 +2504,17 @@ КонецФункции +Процедура УпаковатьЗапрос(Запрос) + + Заголовок = ПолучитьЗначениеЗаголовка("content-encoding", Запрос.Заголовки); + Если Заголовок <> Ложь Тогда + Если НРег(Заголовок) = "gzip" Тогда + Запрос.УстановитьТелоИзДвоичныхДанных(ЗаписатьGZip(Запрос.ПолучитьТелоКакДвоичныеДанные())); + КонецЕсли; + КонецЕсли; + +КонецПроцедуры + #Область ПараметрыПоУмолчанию Функция ЗаголовкиПоУмолчанию() diff --git a/src/DataProcessors/Тесты/Ext/ObjectModule.bsl b/src/DataProcessors/Тесты/Ext/ObjectModule.bsl index 1f61d86..90f8ba2 100644 --- a/src/DataProcessors/Тесты/Ext/ObjectModule.bsl +++ b/src/DataProcessors/Тесты/Ext/ObjectModule.bsl @@ -26,19 +26,22 @@ Тест_ПараметрыЗаписиJson(); Тест_URLБезСхемы(); Тест_ПередачаПараметровВСтрокуЗапроса(); - Тест_ПередачаПараметровВСтрокуЗапросаКомбинированный(); + Тест_ПередачаПараметровВСтрокуЗапросаКомбинированный(); Тест_РезультатКакJsonGet(); Тест_РезультатКакJsonPost(); Тест_РезультатКакДвоичныеДанные(); Тест_РезультатКакТекст(); - Тест_ПередачаПроизвольныхЗаголовков(); + Тест_ПередачаПроизвольныхЗаголовков(); Тест_ОтправкаДанныхФормы(); Тест_ОтправкаJson(); Тест_Таймаут(); Тест_BasicAuth(); Тест_DigestAuth(); #Если Не МобильноеПриложениеСервер Тогда + Тест_ОтправитьGZip(); Тест_ПолучитьGZip(); + Тест_УпаковатьGZip(); + Тест_РаспаковатьGZip(); #КонецЕсли Тест_GetJson(); Тест_PostJson(); @@ -52,7 +55,7 @@ Тест_GetОтключенныйРедирект(); Тест_РедиректСУказаниемURL(); Тест_Ошибка404(); - Тест_РаботаССессиями(); + Тест_РаботаССессиями(); Тест_Options(); Тест_Head(); Тест_Delete(); @@ -275,7 +278,7 @@ ПараметрыЗапроса.Вставить("salary", Формат(100000, "ЧГ=")); ПараметрыЗапроса.Вставить("time", "01:47"); - Ответ = КоннекторHTTP.Get("https://httpbin.org/anything/params", ПараметрыЗапроса); + Ответ = КоннекторHTTP.Get("https://httpbin.org/anything/params", ПараметрыЗапроса); Результат = КоннекторHTTP.КакJson(Ответ); УтверждениеВерно(Ответ.URL, "https://httpbin.org/anything/params?name=%D0%98%D0%B2%D0%B0%D0%BD%D0%BE%D0%B2&name=%D0%9F%D0%B5%D1%82%D1%80%D0%BE%D0%B2&salary=100000&time=01%3A47"); @@ -294,7 +297,7 @@ ПараметрыЗапроса.Вставить("name", СтрРазделить("Иванов,Петров", ",")); ПараметрыЗапроса.Вставить("salary", Формат(100000, "ЧГ=")); - Результат = КоннекторHTTP.GetJson("https://httpbin.org/anything/params?post=Программист", ПараметрыЗапроса); + Результат = КоннекторHTTP.GetJson("https://httpbin.org/anything/params?post=Программист", ПараметрыЗапроса); УтверждениеВерно(Результат["args"]["salary"], "100000"); УтверждениеВерно(Результат["args"]["post"], "Программист"); @@ -375,7 +378,7 @@ УтверждениеВерно(Результат["form"]["comments"], "Постучать в дверь"); УтверждениеВерно(Результат["form"]["custemail"], "vasya@mail.ru"); УтверждениеВерно(Результат["form"]["delivery"], "20:20"); - УтверждениеВерно(Результат["form"]["custtel"], "112"); + УтверждениеВерно(Результат["form"]["custtel"], "112"); ТестПройден("Тест_ОтправкаДанныхФормы"); @@ -420,7 +423,27 @@ ТестПройден("Тест_ПолучитьGZip"); КонецПроцедуры + +Процедура Тест_ОтправитьGZip() + Json = Новый Структура; + Json.Вставить("field", "value"); + Json.Вставить("field2", "value2"); + Заголовки = Новый Соответствие; + Заголовки.Вставить("Content-Encoding", "gzip"); + Результат = КоннекторHTTP.PostJson("http://httpbin.org/anything", Json, Новый Структура("Заголовки", Заголовки)); + + ТелоЗапроса = ПолучитьДвоичныеДанныеИзBase64Строки(СтрРазделить(Результат["data"], ",")[1]); + ИсходноеЗначение = КоннекторHTTP.JsonВОбъект(КоннекторHTTP.ПрочитатьGZip(ТелоЗапроса)); + + УтверждениеВерно(Результат["headers"]["Content-Encoding"], "gzip"); + УтверждениеВерно(ИсходноеЗначение["field"], Json["field"]); + УтверждениеВерно(ИсходноеЗначение["field2"], Json["field2"]); + + ТестПройден("Тест_ОтправитьGZip"); + +КонецПроцедуры + Процедура Тест_BasicAuth() Результат = КоннекторHTTP.GetJson("https://user:pass@httpbin.org/basic-auth/user/pass"); @@ -866,6 +889,28 @@ КонецПроцедуры +Процедура Тест_УпаковатьGZip() + + ИсходныеДанные = ПолучитьДвоичныеДанныеИзСтроки("Привет, Мир!", КодировкаТекста.UTF8, Ложь); + СжатыеДанные = ПолучитьДвоичныеДанныеИзBase64Строки("H4sIAAAAAAAA/wEVAOr/0J/RgNC40LLQtdGCLCDQnNC40YAhilS6PhUAAAA="); + + УтверждениеВерно(КоннекторHTTP.ЗаписатьGZip(ИсходныеДанные), СжатыеДанные); + + ТестПройден("Тест_УпаковатьGZip"); + +КонецПроцедуры + +Процедура Тест_РаспаковатьGZip() + + СжатыеДанные = ПолучитьДвоичныеДанныеИзBase64Строки("H4sIAAAAAAAA/wEVAOr/0J/RgNC40LLQtdGCLCDQnNC40YAhilS6PhUAAAA="); + Данные = КоннекторHTTP.ПрочитатьGZip(СжатыеДанные); + + УтверждениеВерно(ПолучитьСтрокуИзДвоичныхДанных(Данные, КодировкаТекста.UTF8), "Привет, Мир!"); + + ТестПройден("Тест_РаспаковатьGZip"); + +КонецПроцедуры + #КонецОбласти Функция ИзвлечьExecution(Ответ)