HTTP-запросы
Общая информация
- Клиент - некоторая система, которая инициирует соединение и посылает запрос.
- Сервер - программное обеспечение, которое ожидает установку соединения от клиента, получает запрос, выполняет некоторые действия и возвращает ответ клиенту.
В основе HTTP-взаимодействия лежит понятие URI (или, в более простом варианте - URL) - универсального идентификатора ресурса, который описан к стандарте RFC 3986. Взаимодействие осуществляется с помощью запросов. Каждый запрос содержит несколько частей: стартовая строка (определяет тип сообщения), заголовки (определяет параметры запроса) и тело сообщения (дополнительные данные запроса, тело сообщения может быть пустым).
метод uri HTTP/версия
. Рассмотрим, из чего
состоит стартовая строка:- метод - это определение операции, которую необходимо выполнить с ресурсом, которую описан с помощью URI. Состоит из любых символов US-ASCII (кроме управляющих символов и разделителей). В принципе, название метода может быть любым, но рекомендуется придерживаться набора методов, который описан в спецификации HTTP 1.1 (RFC 2616).
- uri - описывает путь до конкретного ресурса на том сервере, который будет выполнять запрос. Запрос будет выполняться над данными, которые адресуются указанным URI. Если метод, указанный в запросе, не требует указания какого-либо ресурса, вместо URI следует указать символ "*".
- версия - указывается версия протокола HTTP. В настоящий момент это версия 1.1.
HTTP/версия код-состояния пояснение
. Рассмотрим подробнее содержимое
стартовой строки ответа:- версия - номер версии HTTP-протокола, аналогично стартовой строки запроса. В настоящий момент это версия 1.1.
- код-состояния - описывает результат выполнения запроса. Код состояния может сообщать о том, что запрос выполнен успешно, что во время запроса произошла какая-то ошибка или что запрос нужно повторить, изменив параметры запроса.
- пояснение - текстовое пояснение результата выполнения запроса. Данный текст не содержит символов перевода строки и возврата каретки.
Заголовки запроса — это набор именованных параметров запроса. Каждый запрос может содержать различный набор таких параметров. Заголовки делятся на 4 большие части: общие заголовки (используются как в запросах, так и в ответах), заголовки запроса (используются только в запросах), заголовки ответа (используются только в ответах) и заголовки сущностей (сопровождают каждую сущность сообщений, используются как в запросах, так и в ответах). Имена заголовков не чувствительны к регистру символов. Запрос может содержать несколько заголовков с одинаковым именем. Такое допускается только в том случае, если несколько значений заголовка могут быть перечислены через символ «,», а также если порядок следования значений в заголовке не изменяет семантику заголовка.
Таким образом HTTP-взаимодействие выполняется следующим образом:
- Клиент устанавливает соединение с сервером.
- Клиент готовит запрос и отправляет этот запрос серверу.
- Сервер принимает запрос и пытается выполнить действия, указанные в запросе.
- Результат выполнения запроса сервер оформляет в виде ответа, где код состояния содержит суть ответа. Затем ответ отправляется обратно клиенту
- Клиент получает ответ и анализирует код состояния. По результатам анализа клиент принимает решение о дальнейших действиях.
«1С:Исполнитель» может выступать только в качестве клиента для протокола HTTP.
Методы HTTP-запроса
Метод | Описание |
---|---|
CONNECT | Устанавливает туннель к серверу, определенному URI из запроса |
DELETE | Удаляет данные, которые идентифицируются URI из запроса |
GET | Позволяет запросить содержимое какого-либо ресурса или выполнить какое-либо действие |
HEAD | Позволяет получить метаданные, проверить наличие какого-либо ресурса или узнать, что изменилось с момента последнего обращения. Ответ сервера на содержит тела |
OPTIONS | Используется для определения возможностей веб-сервера или параметров соединения для конкретного ресурса |
PATCH | Аналогичен запросу PUT, но применяется к фрагменту данных ресурса |
POST | Позволяет клиенту передать на сервер какие-то данные. Эти данные, скорее всего, будут обработаны сервером |
PUT | Позволяет клиенту передать на сервер какие-то данные. Эта данные, скорее всего, заменят те данные, которые сейчас адресуются URI из запроса |
TRACE | Возвращает полученный запрос обратно клиенту. Позволяет клиенту узнать, что добавляют или изменяют в оригинальном запросе промежуточные узлы (через которые проходит запрос) |
Описание методов, приведенное в таблице, является рекомендуемым поведением. Фактическое поведение целиком и полностью определяется фактической реализацией сервера HTTP-запроса.
Коды состояния
Код | Класс | Описание |
---|---|---|
1хх | Информационный | Информирование о процессе передачи запроса |
2хх | Успех | Информирование о том, что запрос успешно выполнился |
3хх | Перенаправление | Сообщает клиенту о том, что для выполнения запроса необходимо выполнить запрос с другими параметрами. Заголовки ответа содержат информацию о том, что надо изменить в запросе |
4хх | Ошибка клиента | Указывает, что запрос клиента содержит ошибку |
5хх | Ошибка сервера | Указывает, что во время выполнения запроса на сервере произошла ошибка |
Кодирование URL адреса в ЗапросHttp
В адресе запроса могут содержаться символы, использование которых недопустимо в URI. Для успешного выполнения такого запроса недопустимые символы должны быть закодированы с использованием символа «%». Однако разработчик не всегда может гарантировать кодирование всех недопустимых символов. В результате в адресе запроса могут встречаться допустимые символы, закодированные недопустимые символы и недопустимые символы, которые не были закодированы.
Для того чтобы обеспечить успешное выполнение запроса в любом случае, ЗапросHttp во входящей строке сохраняет процент-кодированные представления символов, которые там уже есть, а все недопустимые символы кодирует. Входящая строка адреса обрабатывается следующим образом: если за символом процента (%) следует значение, допустимое для кода символа (два шестнадцатеричных значения), то считается, что это код символа. Иначе считается, что это знак процента, который будет закодирован (%25).
Входящий адрес URL (строка) разделяется на группы и каждая группа кодируется отдельно (например, путь, запрос и т. д.). Группы адреса соответствуют описанию стандарта RFC3986: схема (scheme), основание (authority), путь (path), запрос (query), фрагмент (fragment):
Допустимыми являются все разделители внутри сегментов, которые указаны в стандарте RFC 3986: «!», «&», «'», «+», «*», «$», «(», «)», «,», «;», «=». Также для сегментов запрос и фрагмент допустимы «/», «?».
Символы, которые являются разделителями сегментов, не меняются «:» / «/» / «?» / «#» / «[» / «]» / «@». Не меняются разрешенные к использованию во всех частях URL-адреса символы: «-» / «.» / «_» / «~».
Если во входящей строке представлены символы национальных алфавитов (то есть не латиница, в частности — русские буквы), то они также кодируются. Если такие символы присутствуют в доменной части строки, то выполняется IDN-кодирование. Если такие символы присутствуют в других частях URL, то выполняется процентное кодирование.
Примеры процентного кодирования:
Исходный адрес запроса Адрес запроса после преобразований: пробел и обратный слеш были закодированы |
https://yandex.ru/maps%2F%3Ftest1%2Ftest 2%5Ctest3\test4 https://yandex.ru/maps%2F%3Ftest1%2Ftest%202%5Ctest3%5Ctest4 |
Исходный адрес запроса Адрес запроса после преобразований: текст не изменился, так как после процента допустимый код символа |
http://test.ru/search=aa%2Faa http://test.ru/search=aa%2Faa |
Исходный адрес запроса Адрес запроса после преобразований: процент был закодирован |
http://test.ru/search=100% http://test.ru/search=100%25 |
Пример IDN-кодирования:
Исходный адрес Адрес после преобразования |
http://яндекс.рф http://xn--d1acpjx3f.xn--p1ai |
Объектная модель
Теперь, когда мы знаем, как устроено клиент-серверное взаимодействие с использованием HTTP-запросов, можно наложить на эту схему объектную модель, которую предоставляет «1С:Исполнитель».
В качестве основы всей модели выступает тип КлиентHttp. Экземпляр этого типа может быть получен из свойства глобального контекста КлиентHttp. Он содержит базовые параметры HTTP-взаимодействия.
В тоже время, нам может потребоваться в один момент времени работать с несколькими серверами. Поэтому экземпляр типа КлиентHttp может создавать новые экземпляры типа КлиентHttp, которые будут получать все параметры из своего базового экземпляра, кроме некоторых параметров, которые можно изменить при создании копии. Другими словами - будет создавать измененная копия родительского экземпляра. Говоря про такую возможность (создание нового экземпляра на базе существующего) мы будет говорить, что существующий экземпляр выступает в роли фабрики. Экземпляр типа КлиентHttp, который предоставляет «1С:Исполнитель», будем называть базовым экземпляром.
пер МойКлиент = КлиентHttp.СБазовымUrl("http://example.com")
знч ДоверенныеСертификаты = новый ХранилищеPkcs12()
ДоверенныеСертификаты.ДобавитьСертификат("1", СертификатГост)
исп Ответ = КлиентHttp.СКриптоПроTls()
.СПараметрамиЗащиты(новый ПараметрыЗащищенногоСоединения(ДоверенныеСертификаты))
.СТаймаутомЗапроса(15с)
.ЗапросGet("https://website-address.ru")
.Выполнить()
Теперь мы имеем экземпляр, который выступает в роли клиента и нам необходимо выполнить запрос к серверу, который мы указали при создании клиента. Для этого мы от экземпляра типа КлиентHttp получим экземпляр типа ЗапросHttp.
Тип ЗапросHttp служит для формирования запроса от клиента серверу и получения ответа от сервера. Ответ от сервера поступает в виде экземпляра типа ОтветHttp.
Если мы хотим выполнить запрос, описанный в стандарте HTTP 1.1, то можно использовать метод КлиентHttp.ЗапросGet() и аналогичные ему (все поддерживаемые имена HTTP-методов перечислены в таблице Методы HTTP-запроса). В этом случае в метод необходимо передать только URI на сервере, к которому будет применяться запрос.
пер Запрос = МойКлиент.ЗапросGet("/path/resource?param1=value1¶m2=value")
пер Запрос = МойКлиент.СоздатьЗапрос("GET", "/path/resource?param1=value1¶m2=value")
Получив экземпляр типа ЗапросHttp мы можем указать ему нужные заголовки (задав их явно или переопределив уже существующие). Для этого есть свойство ЗапросHttp.Заголовки, которое предоставляет доступ ко всей коллекции заголовков данного запроса. Свойство имеет тип ЗаголовкиHttp.
Также ЗапросHttp позволяет работать как с одним заголовком (методы ДобавитьЗаголовок()/УстановитьЗаголовок()/УдалитьЗаголовок()), так и с несколькими заголовками сразу (методы ДобавитьЗаголовки()/УстановитьЗаголовки()/ОчиститьЗаголовки()). С помощью методов добавления/установки заголовков нельзя изменять заголовки Content-Type и Transfer-Encoding. Для изменения заголовка Content-Type предназначен метод УстановитьТипСодержимого(). Для установки информации о клиентском приложении (заголовок User-Agent) предназначен метод УстановитьUserAgent().
- УстановитьТело(Тело: Строка): ЗапросHttp — устанавливает тело запроса из строки.
- УстановитьТело(Поток: ПотокЧтения): ЗапросHttp — в этом случае запрос будет выполнен (ЗапросHttp.Выполнить()) с использованием Chunked transfer encoding. Чтение переданного потока будет осуществляться только в момент вызова метода ЗапросHttp.Выполнить(). После выполнения отправки переданный поток будет закрыт.
- УстановитьТело(Поток: ПотокЧтения, Размер: Число): ЗапросHttp — чтение переданного потока будет осуществляться только в момент вызова метода ЗапросHttp.Выполнить(). После выполнения отправки переданный поток будет закрыт.
- УстановитьТело(Файл: Файл): ЗапросHttp — чтение переданного файла будет осуществляться только в момент вызова метода ЗапросHttp.Выполнить().
После того, как наш запрос готов, его необходимо выполнить. Для этого служит метод ЗапросHttp.Выполнить(). Вызов этого метода приведет к фактическому выполнению запроса. "Внутри" этого вызова будут выполнены все действия HTTP-взаимодействия. Результат вызова будет помещен в экземпляр типа ОтветHttp и этот экземпляр вернется для анализа и получения данных, которые вернул сервер.