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

16.02.17

Разработка - Запросы

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/2017: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/2017:14:40:52 +0400] "HEAD /api/order_items/93076?order_item[qnt_income]=30 HTTP/1.1"
"Может быть я что-то не так делаю?" - задал я себе вопрос. Но в интернете и в мануалах не было никаких подсказок. Что ж, метод научного тыка еще никто не отменял. Для начала я попробовал сделать так: 
Соединение.ВызватьHTTPМетод("фывфыв",Запрос);
В логах получил:
127.0.0.1 - - [16/Feb/2017: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/2017: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, проверял ради спортивного интереса.
Как сказал бы всем известный Вовочка из знаменитого анекдота: "Где логика?".

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

HTTP запрос PUT ошибки 1С

См. также

SALE! 15%

Инструментарий разработчика Роли и права Запросы СКД Программист Платформа 1С v8.3 Управляемые формы Запросы Система компоновки данных Конфигурации 1cv8 Платные (руб)

Набор инструментов программиста и специалиста 1С для всех конфигураций на управляемых формах. В состав входят инструменты: Консоль запросов, Консоль СКД, Консоль кода, Редактор объекта, Анализ прав доступа, Метаданные, Поиск ссылок, Сравнение объектов, Все функции, Подписки на события и др. Редактор запросов и кода с раскраской и контекстной подсказкой. Доработанный конструктор запросов тонкого клиента. Продукт хорошо оптимизирован и обладает самым широким функционалом среди всех инструментов, представленных на рынке.

10000 руб.

02.09.2020    159668    875    399    

862

Запросы Программист Бесплатно (free)

Увидел cheatsheet по SQL и захотелось нарисовать подобное, но про запросы.

18.10.2024    9944    sergey279    18    

64

Запросы Программист Платформа 1С v8.3 Запросы Конфигурации 1cv8 Бесплатно (free)

Столкнулся с интересной ситуацией, которую хотел бы разобрать, ввиду её неочевидности. Речь пойдёт про использование функции запроса АВТОНОМЕРЗАПИСИ() и проблемы, которые могут возникнуть.

11.10.2024    5204    XilDen    36    

80

Запросы Программист Запросы Бесплатно (free)

Отлаживая взаимодействие с базой данных, мы регулярно сталкиваемся с зависающими или подозрительно долго выполняющимися обращениями, негативно влияющими на производительность. О том, как в PostgreSQL выявить подозрительные запросы, основываясь на доступной о них информации, расскажем в статье.

16.08.2024    7941    user1840182    5    

28

Математика и алгоритмы Запросы Программист Платформа 1С v8.3 Запросы Бесплатно (free)

Рассмотрим быстрый алгоритм поиска дублей с использованием hash функции по набору полей шапки и табличных частей.

08.07.2024    2405    ivanov660    9    

22

Запросы СКД Программист Стажер Система компоновки данных Россия Бесплатно (free)

Часто при разработке отчетов в СКД возникает ситуация, когда не совсем понятно, почему отчет выводит не те данные, которые нужны, либо не выводит вовсе. Возникает потребность увидеть конечный запрос, который формирует СКД. Как это сделать, рассмотрим в этой статье.

15.05.2024    8726    implecs_team    6    

47

Запросы Программист Стажер Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Часто поступают задачи по произвольному распределению общих сумм. После распределения иногда пропадают копейки. Суть решения добавить АвтоНомерЗаписи() в ВТ распределения, и далее используя функции МАКСИМУМ или МИНИМУМ можем положить разницу копеек в первую или последнюю строку знаменателя распределения.

11.04.2024    3395    andrey_sag    10    

36
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. Ликреонский 242 17.02.17 08:11 Сейчас в теме
Странно:
Соединение.ВызватьHTTPМетод("PUT",Запрос);
Соединение.ВызватьHTTPМетод("PUT ",Запрос);

Разница в один пробел и в этом все дело?
2. hspeed79 96 17.02.17 09:26 Сейчас в теме
(1) да, удивительно, но факт =)
3. Ликреонский 242 17.02.17 10:10 Сейчас в теме
(2)Чудны дела твои, Нуралиев :)
lostcay; user1485967; simonovich; Aparatus; bulpi; +5 1 Ответить
4. pbazeliuk 1969 17.02.17 10:49 Сейчас в теме
Спасибо, полезная информация.
5. frkbvfnjh 805 17.02.17 15:36 Сейчас в теме
Вам бы на форуме специалистов поднять это вопрос. Возможно это как всегда ошибка в платформе. Вы наверное первый кто воспользовался PUT в 1С. Есть чувство что сами разработчики даже проверять не стали...
Chizhik2020; EMelihoff; +2 Ответить
6. AlX0id 17.02.17 16:17 Сейчас в теме
(5)
ЗапросКСайту = Новый HTTPЗапрос(ТекстЗапроса,ЗаголовокЗапроса(Заголовки));
	
	Если Тело <> Неопределено Тогда
		ЗапросКСайту.УстановитьТелоИзСтроки(Тело, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать); 
	КонецЕсли;
	
Результат = Соединение.ВызватьHTTPМетод("PUT", ЗапросКСайту, РезультатИмяФайла);


Так работало еще с полгода назад.
Nikitos_NSK; Yimaida; +2 Ответить
7. starik-2005 3088 17.02.17 16:42 Сейчас в теме
(6) все зависит от того, как работает. Если на стороне сайта нет разницы, пут пришел или хид, то и так сработает. Если с файлом генерится пут, то, видимо, какая-то мистика в 1С.
dj_serega; +1 Ответить
8. dj_serega 393 17.02.17 17:25 Сейчас в теме
(7)
на стороне сайта нет разницы

Я бы хотел уточнить. Может на стороне вебсервера сайта? :)
9. AlX0id 17.02.17 18:51 Сейчас в теме
(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. Так что, видимо, дело-то не в пробеле, а в отсутствии тела как такового..
insurgut; Gendelf; COMPER; vld_dmn; websamson; A1WEB; json; Yimaida; +8 Ответить
10. hspeed79 96 17.02.17 19:40 Сейчас в теме
(9) Понятно, добрая 1С не дает нам ошибиться и отеческой рукой меняет метод за нас.
Спасибо за подсказку, все таки у меня изначально был некорректный скрипт.
insurgut; +1 Ответить
11. vitaliy1911 40 20.02.17 09:32 Сейчас в теме
да, сталкивался с этой проблемой. довольно странное поведение. вот тут поднимал эту тему http://www.forum.mista.ru/topic.php?id=784496
13. Evil Beaver 8244 12.03.17 08:40 Сейчас в теме
Ваабче-то, метод PUT (как и POST) предполагает наличие тела, т.е. именно того, что вы будете "Помещать" и "Постить". Без тела эти методы смысла не имеют. Другой вопрос, имеет ли право 1С подменять метод, если не видит тело. На мой взгляд, тут должно быть исключение, а не неочевидная замена на HEAD. Но в любом случае, без "тела" эти методы не должны применяться.
CratosX; Pandu; WinterIT; Merkalov; Irwin; Drivingblind; vld_dmn; ness; +8 Ответить
14. ness 09.08.18 18:23 Сейчас в теме
Было полезно, спасибо.
15. dsdred 3631 20.08.18 23:09 Сейчас в теме
http-сервис поднял на 8.3.10.2650 + IIS 6, обращался из 8.3.12.1595, ошибку не словил. Наверное исправили...
Использовал метод Любой(ANY)
Функция PAPI_ALL(Запрос)
	Ответ = Новый HTTPСервисОтвет(200);
	Результат = "";
	Результат = Результат + Запрос.HTTPМетод + Символы.ПС;
	Результат = Результат + Запрос.БазовыйURL + Символы.ПС;
	Результат = Результат + Запрос.ОтносительныйURL + Символы.ПС + Символы.ПС;
	Результат = Результат + "Заголовки:" + Символы.ПС;
	Для каждого Параметр Из Запрос.Заголовки Цикл
		Результат = Результат + Параметр.Ключ + ":" + Параметр.Значение + Символы.ПС;
	КонецЦикла;
	Результат = Результат + Символы.ПС + "Параметры URL:" + Символы.ПС;
	Для каждого Параметр Из Запрос.ПараметрыURL Цикл
		Результат = Результат + Параметр.Ключ + ":" + Параметр.Значение + Символы.ПС;
	КонецЦикла;
	Результат = Результат + Символы.ПС + "Параметры запроса:" + Символы.ПС;
	Для каждого Параметр Из Запрос.ПараметрыЗапроса Цикл
		Результат = Результат + Параметр.Ключ + ":" + Параметр.Значение + Символы.ПС;
	КонецЦикла;
	Ответ.УстановитьТелоИзСтроки(Результат);
	
	//Ответ.Заголовки.Вставить("Content-Type","text/html; charset=utf-8");
	Ответ.Заголовки.Вставить("Content-Type","text/plain; charset=utf-8");

	Возврат Ответ
КонецФункции
Показать



Обращался так:
&НаСервере
Процедура ВсеМетодыНаСервере()
	перПорт = 0;
	перСервер = "127.0.0.1";
	перПользователь = "Администратор";
	перПароль = "";
	
	Попытка		
		Если перПорт <= 0 Тогда 
			HTTPСоединение = Новый HTTPСоединение(перСервер,,перПользователь,перПароль);
		Иначе 
			HTTPСоединение = Новый HTTPСоединение(перСервер,перПорт,перПользователь,перПароль);
		КонецЕсли;	
	Исключение
		Сообщить("Подключение не прошло по причине "+ОписаниеОшибки());
		
		//Подчичаем соединение
		HTTPСоединение = Неопределено;
		Возврат;
	КонецПопытки;
	
	МассивМетодов = МассивВсехМетодов();
	
	Для Каждого элМассива из МассивМетодов Цикл  
		
		Результат = Результат + "Метод: [" + элМассива + "]++" + Символы.ПС;
		перРесурсНаСервере = "/DemoSSL2_4_6_146/hs/PAPI/"+элМассива+"?parametr1=13¶metr2=test";
		
		Результат = Результат + "{Без тела запроса}" + Символы.ПС;
		HTTPЗапрос = Новый HTTPЗапрос(перРесурсНаСервере);
		//Тело отсутствует
		HTTPОтвет = HTTPСоединение.ВызватьHTTPМетод(элМассива,HTTPЗапрос);
		
		//Получаем ответный текст или текст ошибки
		Ответочка = HTTPОтвет.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);

		Результат = Результат + Ответочка + Символы.ПС + Символы.ПС;
		
		Результат = Результат + "{С телом запроса}" + Символы.ПС;
		//Тело присутствует
		HTTPЗапрос.УстановитьТелоИзСтроки("Тело Запроса - просто текст");
		HTTPОтвет = HTTPСоединение.ВызватьHTTPМетод(элМассива,HTTPЗапрос);
		
		//Получаем ответный текст или текст ошибки
		Ответочка = HTTPОтвет.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
		
		Результат = Результат + Ответочка + Символы.ПС;
		
		Результат = Результат +  "Метод: [" + элМассива + "]--" + Символы.ПС + Символы.ПС;
	КонецЦикла;	
		
КонецПроцедуры

&НаСервереБезКонтекста
Функция МассивВсехМетодов()
	МассивМетодов = новый Массив;
	МассивМетодов.Добавить("GET");
	МассивМетодов.Добавить("HEAD");
	МассивМетодов.Добавить("PUT");
	МассивМетодов.Добавить("POST");
	МассивМетодов.Добавить("DELETE");
	МассивМетодов.Добавить("PATCH");
	МассивМетодов.Добавить("MERGE");
	МассивМетодов.Добавить("OPTIONS");
	МассивМетодов.Добавить("TRACE");
	МассивМетодов.Добавить("CONNECT");
	Возврат МассивМетодов;
КонецФункции	
Показать




GET


HEAD


PUT


POST


DELETE


PATCH


MERGE


OPTIONS


TRACE


CONNECT
NewLifeMan; +1 Ответить
16. insurgut 208 25.12.18 13:03 Сейчас в теме
На примере взаимодействия с ProfitBase никак не мог заставить работать метод PATCH.

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

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


в корректный

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


все заработало.
17. Danila-Master 118 30.03.20 09:43 Сейчас в теме
У httpсоединения есть собственные методы put и patch. Это Записать() и Изменить() соответственно.

Чем они отличаются от ВызватьHTTPМетод()?
18. tnic001in 15.10.21 11:48 Сейчас в теме
Я использую как раз put и patch через Записать и Изменить, никаких траблов с ними не было и не надо танцев с заголовками. Платформа даже древняя - 1С:Предприятие 8.3 (8.3.12.1790)
А ВызватьHTTPМетод просто более универсальный, плюс ответ сразу в файл можно вывалить.

Пример ниже, не претендует на правильность кода)
Прикрепленные файлы:
Оставьте свое сообщение