Отправка PUT запроса средствами 1С 8.3

HTTP запрос с использованием метода PUT средствами 1С 8.3 на практике — проблема и решение

При разработке процедуры отправки на сайт информации из 1С с версией платформы 8.3.9.2170 столкнулся с проблемой: разработчик сайта предоставил мне возможность записывать нужную информацию только при помощи HTTP запроса методом PUT.

Недолго думая, я набросал простенький код:
    Соединение = Новый HTTPСоединение("www.mysite.ru");
Заголовки = Новый Соответствие;
Заголовки["Content-Type"] = "application/x-www-form-urlencoded";
Запрос = Новый HTTPЗапрос("/api/order_items/93076?order_item[qnt_income]=30", Заголовки);
Соединение.Записать(Запрос);

По результатам выполнения в соответствующей строке заказа покупателя на сайте должно было проставиться количество поступившего на склад товара.

Однако, как вы уже наверно поняли, ничего не произошло. После того как я убедился, что на сайте ошибок нет  (путем отправки аналогичного запроса через плагин к Хрому), я запустил на своем локальном компьютере web-сервер и стал экспериментировать.
Сразу же выяснилась странная вещь: вышеприведенный код генерирует не PUT, а HEAD запрос!
В логах апача я увидел следующее:
127.0.0.1 — — [16/Feb/2024:14:38:54 +0400] «HEAD /api/order_items/93076?order_item[qnt_income]=30 HTTP/1.1»
Я немного удивился (в руководстве ведь было черным по белому написано PUT), но не растерялся — можно ведь вызвать метод напрямую:
Соединение.ВызватьHTTPМетод("PUT",Запрос);
В логах то же самое:
127.0.0.1 — — [16/Feb/2024:14:40:52 +0400] «HEAD /api/order_items/93076?order_item[qnt_income]=30 HTTP/1.1»
«Может быть я что-то не так делаю?» — задал я себе вопрос. Но в интернете и в мануалах не было никаких подсказок. Что ж, метод научного тыка еще никто не отменял. Для начала я попробовал сделать так: 
Соединение.ВызватьHTTPМетод("фывфыв",Запрос);
В логах получил:
127.0.0.1 — — [16/Feb/2024:14:53:03 +0400] «?????? /api/order_items/93076?order_item[qnt_income]=30 HTTP/1.1»

Любопытно, значит 1С заменяет конкретно метод PUT (чем же он 1С не угодил?).

После еще нескольких попыток я пришел к варианту: 
Соединение.ВызватьHTTPМетод("PUT ",Запрос);
В логах получил:
127.0.0.1 — — [16/Feb/2024:14:53:03 +0400] «PUT  /api/order_items/93076?order_item[qnt_income]=30 HTTP/1.1»

И уже этот вариант отработал на сайте и все остались довольны.

UPD.

Алексей 1 (AlX0id)  подсказал более корректное решение проблемы: необходимо задать тело запроса, любое, даже пустое. Например, сработает такой вариант:
    Соединение = Новый HTTPСоединение("www.mysite.ru");
Заголовки = Новый Соответствие;
Заголовки["Content-Type"] = "application/x-www-form-urlencoded";
Запрос = Новый HTTPЗапрос("/api/order_items/93076?order_item[qnt_income]=30", Заголовки);
Запрос.УстановитьТелоИзСтроки("", КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
Соединение.Записать(Запрос);

И уже совсем правильно, наверное, передавать в теле запроса сами значения параметров.

Вывод следующий: PUT запрос без тела платформа 1С считает ошибочным и заменяет метод на HEAD.
Любопытно что POST запрос без тела 1С никак не отслеживает и не превращает в GET, проверял ради спортивного интереса.
Как сказал бы всем известный Вовочка из знаменитого анекдота: «Где логика?».

Надеюсь кому-то моя публикация сбережет несколько часов жизни в поисках ответа. =)))

16 Comments

  1. Ликреонский

    Странно:

    Соединение.ВызватьHTTPМетод(«PUT»,Запрос);
    Соединение.ВызватьHTTPМетод(«PUT «,Запрос);

    Разница в один пробел и в этом все дело?

    Reply
  2. hspeed79

    (1) да, удивительно, но факт =)

    Reply
  3. Ликреонский

    (2)Чудны дела твои, Нуралиев 🙂

    Reply
  4. pbazeliuk

    Спасибо, полезная информация.

    Reply
  5. frkbvfnjh

    Вам бы на форуме специалистов поднять это вопрос. Возможно это как всегда ошибка в платформе. Вы наверное первый кто воспользовался PUT в 1С. Есть чувство что сами разработчики даже проверять не стали…

    Reply
  6. AlX0id

    (5)

    ЗапросКСайту = Новый HTTPЗапрос(ТекстЗапроса,ЗаголовокЗапроса(Заголовки));
    
    Если Тело <> Неопределено Тогда
    ЗапросКСайту.УстановитьТелоИзСтроки(Тело, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
    КонецЕсли;
    
    Результат = Соединение.ВызватьHTTPМетод(«PUT», ЗапросКСайту, РезультатИмяФайла);

    Так работало еще с полгода назад.

    Reply
  7. starik-2005

    (6) все зависит от того, как работает. Если на стороне сайта нет разницы, пут пришел или хид, то и так сработает. Если с файлом генерится пут, то, видимо, какая-то мистика в 1С.

    Reply
  8. dj_serega

    (7)

    на стороне сайта нет разницы

    Я бы хотел уточнить. Может на стороне вебсервера сайта? 🙂

    Reply
  9. AlX0id

    (7)

    Полез проверять.. Думаю, вроде фиддлером все проверял, и в документации был именно PUT..

    &НаКлиенте
    Процедура Команда2(Команда)
    
    Тело = «фывафыва»;
    Соединение = Новый HTTPСоединение(«mysite.tk»);
    Заголовки = Новый Соответствие;
    Заголовки[«Content-Type»] = «application/x-www-form-urlencoded»;
    Запрос = Новый HTTPЗапрос(«/api/order_items/93076?order_item[qnt_income]=30», Заголовки);
    Запрос.УстановитьТелоИзСтроки(Тело, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
    Соединение.ВызватьHTTPМетод(«PUT»,Запрос);
    
    КонецПроцедуры
    
    &НаКлиенте
    Процедура Команда3(Команда)
    
    Тело = «фывафыва»;
    Соединение = Новый HTTPСоединение(«mysite.tk»);
    Заголовки = Новый Соответствие;
    Заголовки[«Content-Type»] = «application/x-www-form-urlencoded»;
    Запрос = Новый HTTPЗапрос(«/api/order_items/93076?order_item[qnt_income]=30», Заголовки);
    Соединение.ВызватьHTTPМетод(«PUT»,Запрос);
    
    КонецПроцедуры
    

    Показать

    Вот Команда2 — дает PUT. А Команда3 — уже HEAD. Так что, видимо, дело-то не в пробеле, а в отсутствии тела как такового..

    Reply
  10. hspeed79

    (9) Понятно, добрая 1С не дает нам ошибиться и отеческой рукой меняет метод за нас.

    Спасибо за подсказку, все таки у меня изначально был некорректный скрипт.

    Reply
  11. vitaliy1911

    да, сталкивался с этой проблемой. довольно странное поведение. вот тут поднимал эту тему http://www.forum.mista.ru/topic.php?id=784496

    Reply
  12. kodnik
  13. Evil Beaver

    Ваабче-то, метод PUT (как и POST) предполагает наличие тела, т.е. именно того, что вы будете «Помещать» и «Постить». Без тела эти методы смысла не имеют. Другой вопрос, имеет ли право 1С подменять метод, если не видит тело. На мой взгляд, тут должно быть исключение, а не неочевидная замена на HEAD. Но в любом случае, без «тела» эти методы не должны применяться.

    Reply
  14. ness

    Было полезно, спасибо.

    Reply
  15. dsdred
    Reply
  16. insurgut

    На примере взаимодействия с ProfitBase никак не мог заставить работать метод PATCH.

    В результате, многие сервисы очень чувствительны в тому, что указывается в заголовках. На моем примере после исправления не

    HTTPЗапрос.Заголовки.Вставить(«Content-type», «application/x-www-form-urlencoded;charset=utf-8»);

    в корректный

    HTTPЗапрос.Заголовки.Вставить(«Content-type», «application/json»);

    все заработало.

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *