Возвращает тело запроса в виде двоичных данных.
Синтаксис
ПолучитьТелоКакДвоичныеДанные()Полное описание, параметры и ограничения
HTTPСервисЗапрос.ПолучитьТелоКакДвоичныеДанные (HTTPServiceRequest.GetBodyAsBinaryData)
HTTPСервисЗапрос (HTTPServiceRequest)
ПолучитьТелоКакДвоичныеДанные (GetBodyAsBinaryData)
Доступен, начиная с версии 8.3.5.
Синтаксис:
ПолучитьТелоКакДвоичныеДанные()
Возвращаемое значение:
Тип: ДвоичныеДанные.
Описание:
Возвращает тело запроса в виде двоичных данных.
Доступность:
Сервер, толстый клиент.
Использование в версии:
Доступен, начиная с версии 8.3.5.
Методическая информация
Практические примеры
Принять свой настоящий POST в HTTP-сервис1С: маршрут, заголовки, строка, байты, поток и файл ответа
HTTPСервисЗапрос поступает от самой платформы в реальный обработчик опубликованного собственного сервиса, а не конструируется фиктивно. Четыре конкретных запроса проверяют route/query/header/UTF8-body, последний возвращает только свежесозданный собственный файл.
Где и как запускать
Полный модуль собственного HTTP-сервиса УчебныйПрием85 новой пустой УчебныйHTTP85, nativehandlerPOST Принять85(Запрос). Полный клиентский модуль и fixtureschema включены, production и реальная сеть не используются.
Подготовка
Только отдельная собственная Windows VM и новая пустая конфигурация УчебныйHTTP858.5.1.1343. Русский язык, совместимость Не использовать, управляемый интерфейс. Нет предметных объектов, расширений, фона и рабочей базы. Автор не публиковал сервис, не отправлял HTTP и не создавал файлы. OwnHTTPSource здесь — полные тексты для вашей ручной изолированной проверки.
Вручную создайте единственного пользователя HttpLab85_ с добавленным новым ненулевым каноническим UUID, разрешите ему стандартную аутентификацию, задайте только свой новый учебный пароль. Назначьте права администрирования пользователей/данных, использования своего HTTP-сервиса и чтения нужных метаданных. Нет производства/персональных данных; код не создает пользователя и не меняет роли/пароль.
Конфигуратор → Общие → HTTP-сервисы: создайте единственный УчебныйПрием85, КорневойURL guide85. Создайте шаблон СобственнаяКарточка с ШаблонURL /lab/{session}, метод POST, Обработчик Принять85. Вставьте весь основной модуль в модуль этого HTTP-сервиса. Не помещайте его в клиентскую форму/общий модуль: реальный Запрос передает платформа этому обработчику.
В своей VM вручную опубликуйте ТОЛЬКО эту новую базу под именем guide85 на отдельном IIS/Apache binding127.0.0.1:18086. Публикуйте только свой HTTP-сервис, не anonymous доступ/production/OData, без redirects/proxy/public listener. Выберите стандартную Basic-аутентификацию собственного тестового пользователя. Configure web-server request body limit4096 байт до попадания в1С; header-limit умеренный, Transfer-Encoding/chunked для этого собственного опыта отклоняется в обработчике.
Путь собственного endpoint: http://127.0.0.1:18086/guide85/hs/guide85/lab/<реальныйUUIDпользователяБазы>?mode=text. NativeБазовыйURL может быть относительной частью /guide85/hs/guide85 либо полным этим loopbackURL; обработчик принимает только эти две явно подготовленные формы. ОтносительныйURL должен быть /lab/UUID безquery. Если ваша публикация выдает иной формат, сначала проверьте его штатно на своем стенде, а не расширяйте guard до любого URL.
В той же базе создайте свою внешнюю обработку УчебныйКлиентПриема85 с одной управляемой формой. Строки Метка85 длиной36, Имя85 длиной100, Пароль85 длиной100, Подтверждение85 длиной100, Статус85 длиной0; булево Начат85. Метка/имя/статус/флаг только для просмотра, пароль защищенно отображается. Назначьте ПриСозданииНаСервере и команду Выполнить85→Выполнить85, вставьте полный поддерживающий модуль формы.
Метка и имя берутся из реального своего текущего пользователя, не задаются произвольным UUID. Введите только пароль собственной тестовой учетной записи. Сначала оставьте фразу пустой: запросов не должно быть. После проверки VM введите СВОЯ ПУБЛИКАЦИЯ127.0.0.1 и один раз нажмите команду. Положительный путь — thin/thick managed этого собственного стенда; не обещается работа web/mobile/внешнейпубликации.
Клиент отправит четыре небольших POST: mode=text, bytes, stream, file, всегда свой UTF-8 текст UUID|Книга|3|250, отдельные Content-Type/X-Guide-Session и реальный Content-Length, сформированный HTTP транспортом. Обработчик сравнит авторизованного пользователя, URLsession, querymode и реальные байты. Никакой arbitraryfilepath/открытый echo/произвольныйSQL тут не принимаются.
В file-ветви сервер1С создаст ровно один новый небольшой временный файл только собственного ответа. GetTempFileName не создает его сам; существующее имя не перезаписывается. После SetBodyFilename нельзя удалять этот файл до фактического формирования ответа платформой. Путь не выводится клиенту/логам. Это не backup/archive, и автор таких файлов не создавал.
По установленной справке свежий серверный временный файл платформой очищается после завершения вызова с отложенным сроком; урок не выдает эту будущую очистку за уже проверенную. Не устраивайте нагрузочный бесконечный тест: запустите только один свой опыт. Закрытие формы не доказывает отсутствие файла при неизвестном HTTP-результате, catch ничего автоматически не удаляет.
Функция Принять85(Запрос)
Попытка
Пользователь = ПроверитьСвойHTTPПользователь85();
Метка = Строка(Пользователь.УникальныйИдентификатор);
Если ТипЗнч(Запрос) <> Тип("HTTPСервисЗапрос") Или Запрос.HTTPМетод <> "POST" Тогда
Возврат Отказ85(405);
КонецЕсли;
База = Запрос.БазовыйURL;
Если База <> "/guide85/hs/guide85" И База <> "http://127.0.0.1:18086/guide85/hs/guide85" Тогда
Возврат Отказ85(400);
КонецЕсли;
Если НайтиЗаголовок85(Запрос.Заголовки, "Host") <> "127.0.0.1:18086"
Или НайтиЗаголовок85(Запрос.Заголовки, "X-Guide-Session") <> Метка
Или НайтиЗаголовок85(Запрос.Заголовки, "Content-Type") <> "text/plain; charset=utf-8"
Или НайтиЗаголовок85(Запрос.Заголовки, "Transfer-Encoding") <> Неопределено Тогда
Возврат Отказ85(400);
КонецЕсли;
Если Запрос.ПараметрыURL.Количество() <> 1 Или Запрос.ПараметрыURL.Получить("session") <> Метка
Или Запрос.ОтносительныйURL <> "/lab/" + Метка Тогда
Возврат Отказ85(404);
КонецЕсли;
Если Запрос.ПараметрыЗапроса.Количество() <> 1 Тогда
Возврат Отказ85(400);
КонецЕсли;
Режим = Запрос.ПараметрыЗапроса.Получить("mode");
Если Режим <> "text" И Режим <> "bytes" И Режим <> "stream" И Режим <> "file" Тогда
Возврат Отказ85(400);
КонецЕсли;
ОжидаемыйТекст = Метка + "|Книга|3|250";
ОжидаемыеБайты = ПолучитьДвоичныеДанныеИзСтроки(ОжидаемыйТекст, "UTF-8", Ложь);
СтрокаДлины = НайтиЗаголовок85(Запрос.Заголовки, "Content-Length");
Если ТипЗнч(СтрокаДлины) <> Тип("Строка") Тогда
Возврат Отказ85(411);
КонецЕсли;
Длина = Число(СтрокаДлины);
Если Строка(Длина) <> СтрокаДлины Или Длина <> ОжидаемыеБайты.Размер() Или Длина > 4096 Тогда
Возврат Отказ85(413);
КонецЕсли;
Если Режим = "text" Тогда
Текст = Запрос.ПолучитьТелоКакСтроку("UTF-8");
Если Текст <> ОжидаемыйТекст Тогда
Возврат Отказ85(400);
КонецЕсли;
ИначеЕсли Режим = "stream" Тогда
ПроверитьСвойПоток85(Запрос.ПолучитьТелоКакПоток(), ОжидаемыеБайты);
Иначе
Байты = Запрос.ПолучитьТелоКакДвоичныеДанные();
Если Байты.Размер() <> Длина Или Base64Строка(Байты) <> Base64Строка(ОжидаемыеБайты) Тогда
Возврат Отказ85(400);
КонецЕсли;
КонецЕсли;
Заголовки = Новый Соответствие;
Заголовки.Вставить("Content-Type", "text/plain; charset=utf-8");
Заголовки.Вставить("X-Guide-Session", Метка);
Ответ = Новый HTTPСервисОтвет(200, , Заголовки);
ТекстОтвета = Метка + "|" + Режим + "|Книга|3|250";
Если Режим = "file" Тогда
ИмяСвоегоФайла = ПолучитьИмяВременногоФайла("guide85.txt");
СвойФайл = Новый Файл(ИмяСвоегоФайла);
Если СвойФайл.Существует() Тогда
ВызватьИсключение "Новое собственное имя уже занято; ничего не перезаписывается";
КонецЕсли;
СвоёТело = ПолучитьДвоичныеДанныеИзСтроки(ТекстОтвета, "UTF-8", Ложь);
СвоёТело.Записать(ИмяСвоегоФайла);
Если Не СвойФайл.Существует() Или СвойФайл.Размер() <> СвоёТело.Размер() Тогда
ВызватьИсключение "Свой небольшой файл ответа не подтвержден";
КонецЕсли;
Ответ.УстановитьИмяФайлаТела(ИмяСвоегоФайла);
Если Ответ.ПолучитьИмяФайлаТела() <> ИмяСвоегоФайла Тогда
ВызватьИсключение "В ответе не тот собственный файл";
КонецЕсли;
Иначе
Ответ.УстановитьТелоИзСтроки(ТекстОтвета, "UTF-8", ИспользованиеByteOrderMark.НеИспользовать);
КонецЕсли;
Возврат Ответ;
Исключение
Возврат Отказ85(400);
КонецПопытки;
КонецФункции
Функция НайтиЗаголовок85(Заголовки, Имя)
Значение = Неопределено;
Найден = Ложь;
Для Каждого Пара Из Заголовки Цикл
Если НРег(Пара.Ключ) = НРег(Имя) Тогда
Если Найден Тогда
ВызватьИсключение "Неоднозначный собственный заголовок";
КонецЕсли;
Найден = Истина;
Значение = Пара.Значение;
КонецЕсли;
КонецЦикла;
Возврат Значение;
КонецФункции
Процедура ПроверитьСвойПоток85(ПотокТела, ОжидаемыеБайты)
ОжидаемыйБуфер = ПолучитьБуферДвоичныхДанныхИзДвоичныхДанных(ОжидаемыеБайты);
Буфер = Новый БуферДвоичныхДанных(128);
Смещение = 0;
Попытка
Если Не ПотокТела.ДоступноЧтение Тогда
ВызватьИсключение "Поток собственного тела не поддерживает чтение";
КонецЕсли;
Пока Истина Цикл
Прочитано = ПотокТела.Прочитать(Буфер, 0, 128);
Если Прочитано = 0 Тогда
Прервать;
КонецЕсли;
Если Смещение + Прочитано > ОжидаемыеБайты.Размер() Тогда
ВызватьИсключение "Собственное тело превышает известный размер";
КонецЕсли;
Для Индекс = 0 По Прочитано - 1 Цикл
Если Буфер[Индекс] <> ОжидаемыйБуфер[Смещение + Индекс] Тогда
ВызватьИсключение "Байт собственного тела не совпал";
КонецЕсли;
КонецЦикла;
Смещение = Смещение + Прочитано;
КонецЦикла;
Если Смещение <> ОжидаемыеБайты.Размер() Тогда
ВызватьИсключение "Собственное тело пришло не полностью";
КонецЕсли;
Исключение
ПотокТела.Закрыть();
ВызватьИсключение;
КонецПопытки;
ПотокТела.Закрыть();
КонецПроцедуры
Функция Отказ85(Код)
Ответ = Новый HTTPСервисОтвет(Код);
Ответ.УстановитьТелоИзСтроки("Учебный запрос отклонен", "UTF-8", ИспользованиеByteOrderMark.НеИспользовать);
Возврат Ответ;
КонецФункции
Функция ПроверитьСвойHTTPПользователь85()
ПроверитьСвойПустойСтенд();
Если ПривилегированныйРежим() Тогда
ВызватьИсключение "Входной привилегированный режим не допускается";
КонецЕсли;
Пользователи = ПользователиИнформационнойБазы.ПолучитьПользователей();
Текущий = ПользователиИнформационнойБазы.ТекущийПользователь();
Если Пользователи.Количество() <> 1 Или Текущий = Неопределено
Или Пользователи[0].УникальныйИдентификатор <> Текущий.УникальныйИдентификатор
Или Лев(Текущий.Имя, СтрДлина("HttpLab85_")) <> "HttpLab85_" Тогда
ВызватьИсключение "Нужен единственный собственный внутренний HTTP-пользователь";
КонецЕсли;
UUIDМетки = Новый УникальныйИдентификатор(Сред(Текущий.Имя, СтрДлина("HttpLab85_") + 1));
Если Текущий.Имя <> "HttpLab85_" + Строка(UUIDМетки)
Или UUIDМетки = Новый УникальныйИдентификатор("00000000-0000-0000-0000-000000000000") Тогда
ВызватьИсключение "Учебный UUID-пользователь не подтвержден";
КонецЕсли;
Если Метаданные.HTTPСервисы.Количество() <> 1 Или Метаданные.HTTPСервисы.Найти("УчебныйПрием85") = Неопределено Тогда
ВызватьИсключение "В своей базе нужен только собственный HTTP-сервис УчебныйПрием85";
КонецЕсли;
Возврат Текущий;
КонецФункции
Процедура ПроверитьСвойПустойСтенд()
Если Метаданные.Справочники.Количество() <> 0 Или Метаданные.Документы.Количество() <> 0 Или Метаданные.Перечисления.Количество() <> 0 Или Метаданные.РегистрыСведений.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0 Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0 Или Метаданные.ПланыВидовХарактеристик.Количество() <> 0 Или Метаданные.ПланыВидовРасчета.Количество() <> 0 Или Метаданные.ПланыСчетов.Количество() <> 0 Или Метаданные.ПланыОбмена.Количество() <> 0 Или Метаданные.Последовательности.Количество() <> 0 Или Метаданные.БизнесПроцессы.Количество() <> 0 Или Метаданные.Задачи.Количество() <> 0 Или Метаданные.ОбщиеРеквизиты.Количество() <> 0 Или Метаданные.ПодпискиНаСобытия.Количество() <> 0 Или Метаданные.РегламентныеЗадания.Количество() <> 0 Или Метаданные.ВнешниеИсточникиДанных.Количество() <> 0 Тогда
ВызватьИсключение "Нужен только свой новый пустой учебный стенд";
КонецЕсли;
Если Метаданные.ЕстьИзмененияРасширениямиКонфигурации() Тогда
ВызватьИсключение "Свой сеанс не должен изменяться расширениями";
КонецЕсли;
Источники = Новый Массив;
Источники.Добавить(ИсточникРасширенийКонфигурации.БазаДанных);
Источники.Добавить(ИсточникРасширенийКонфигурации.СеансАктивные);
Источники.Добавить(ИсточникРасширенийКонфигурации.СеансОтключенные);
Для Каждого Источник Из Источники Цикл
Расширения = РасширенияКонфигурации.Получить(, Источник);
Если ТипЗнч(Расширения) <> Тип("Массив") Тогда
ВызватьИсключение "Native список расширений должен иметь тип Массив";
КонецЕсли;
Если Расширения.Количество() <> 0 Тогда
ВызватьИсключение "В своём новом стенде нет расширений базы или сеанса";
КонецЕсли;
КонецЦикла;
Если ТранзакцияАктивна() Тогда
ВызватьИсключение "Чужая или вложенная активная транзакция не допускается";
КонецЕсли;
КонецПроцедурыПолный модуль своей управляемой формы: четыре настоящих POST в свою публикацию
Обработка собственной CF УчебныйHTTP85: полный модуль управляемой формы
Собственная управляемая форма desktop клиента, четыре POST только в свою новую публикацию 127.0.0.1:18086; здесь запросы/публикация не выполняются.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Пользователь = ПроверитьСвойHTTPПользователь85();
Метка85 = Строка(Пользователь.УникальныйИдентификатор);
Имя85 = Пользователь.Имя;
Пароль85 = "";
Подтверждение85 = "";
Начат85 = Ложь;
Статус85 = "Своя loopback-публикация пока не проверена";
КонецПроцедуры
&НаКлиенте
Процедура Выполнить85(Команда)
Если Начат85 Или Подтверждение85 <> "СВОЯ ПУБЛИКАЦИЯ127.0.0.1" Или Не ЗначениеЗаполнено(Пароль85) Тогда
ВызватьИсключение "Нужен свой пароль своей тестовой учетной записи и один явный опыт";
КонецЕсли;
ПроверитьСеанс85();
Начат85 = Истина;
Попытка
Соединение = Новый HTTPСоединение("127.0.0.1", 18086, Имя85, Пароль85, Новый ИнтернетПрокси(Ложь), 5, Неопределено, Ложь);
Режимы = СтрРазделить("text,bytes,stream,file", ",");
Для Каждого Режим Из Режимы Цикл
Заголовки = Новый Соответствие;
Заголовки.Вставить("Content-Type", "text/plain; charset=utf-8");
Заголовки.Вставить("X-Guide-Session", Метка85);
Запрос = Новый HTTPЗапрос("/guide85/hs/guide85/lab/" + Метка85 + "?mode=" + Режим, Заголовки);
Запрос.УстановитьТелоИзСтроки(Метка85 + "|Книга|3|250", "UTF-8", ИспользованиеByteOrderMark.НеИспользовать);
Ответ = Соединение.ОтправитьДляОбработки(Запрос);
Если Ответ.КодСостояния <> 200 Или Ответ.Заголовки.Получить("X-Guide-Session") <> Метка85
Или Ответ.ПолучитьТелоКакСтроку("UTF-8") <> Метка85 + "|" + Режим + "|Книга|3|250" Тогда
ВызватьИсключение "Полный собственный ответ режима не совпал";
КонецЕсли;
КонецЦикла;
Пароль85 = "";
Статус85 = "Все четыре режима источника собственного POST и ответ из собственного файла проверены";
Исключение
Пароль85 = "";
Статус85 = "Запрос не подтвержден. Никакие автоматические повторы или удаления файла не выполнялись";
ВызватьИсключение "Проверьте только собственную публикацию; пароль/чужое тело в лог не выводятся";
КонецПопытки;
КонецПроцедуры
&НаСервере
Процедура ПроверитьСеанс85()
Пользователь = ПроверитьСвойHTTPПользователь85();
Если Метка85 <> Строка(Пользователь.УникальныйИдентификатор) Или Имя85 <> Пользователь.Имя Тогда
ВызватьИсключение "Показанный собственный пользователь изменен";
КонецЕсли;
КонецПроцедуры
&НаСервере
Функция ПроверитьСвойHTTPПользователь85()
ПроверитьСвойПустойСтенд();
Если ПривилегированныйРежим() Тогда
ВызватьИсключение "Входной привилегированный режим не допускается";
КонецЕсли;
Пользователи = ПользователиИнформационнойБазы.ПолучитьПользователей();
Текущий = ПользователиИнформационнойБазы.ТекущийПользователь();
Если Пользователи.Количество() <> 1 Или Текущий = Неопределено
Или Пользователи[0].УникальныйИдентификатор <> Текущий.УникальныйИдентификатор
Или Лев(Текущий.Имя, СтрДлина("HttpLab85_")) <> "HttpLab85_" Тогда
ВызватьИсключение "Нужен единственный собственный внутренний HTTP-пользователь";
КонецЕсли;
UUIDМетки = Новый УникальныйИдентификатор(Сред(Текущий.Имя, СтрДлина("HttpLab85_") + 1));
Если Текущий.Имя <> "HttpLab85_" + Строка(UUIDМетки)
Или UUIDМетки = Новый УникальныйИдентификатор("00000000-0000-0000-0000-000000000000") Тогда
ВызватьИсключение "Учебный UUID-пользователь не подтвержден";
КонецЕсли;
Если Метаданные.HTTPСервисы.Количество() <> 1 Или Метаданные.HTTPСервисы.Найти("УчебныйПрием85") = Неопределено Тогда
ВызватьИсключение "В своей базе нужен только собственный HTTP-сервис УчебныйПрием85";
КонецЕсли;
Возврат Текущий;
КонецФункции
&НаСервере
Процедура ПроверитьСвойПустойСтенд()
Если Метаданные.Справочники.Количество() <> 0 Или Метаданные.Документы.Количество() <> 0 Или Метаданные.Перечисления.Количество() <> 0 Или Метаданные.РегистрыСведений.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0 Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0 Или Метаданные.ПланыВидовХарактеристик.Количество() <> 0 Или Метаданные.ПланыВидовРасчета.Количество() <> 0 Или Метаданные.ПланыСчетов.Количество() <> 0 Или Метаданные.ПланыОбмена.Количество() <> 0 Или Метаданные.Последовательности.Количество() <> 0 Или Метаданные.БизнесПроцессы.Количество() <> 0 Или Метаданные.Задачи.Количество() <> 0 Или Метаданные.ОбщиеРеквизиты.Количество() <> 0 Или Метаданные.ПодпискиНаСобытия.Количество() <> 0 Или Метаданные.РегламентныеЗадания.Количество() <> 0 Или Метаданные.ВнешниеИсточникиДанных.Количество() <> 0 Тогда
ВызватьИсключение "Нужен только свой новый пустой учебный стенд";
КонецЕсли;
Если Метаданные.ЕстьИзмененияРасширениямиКонфигурации() Тогда
ВызватьИсключение "Свой сеанс не должен изменяться расширениями";
КонецЕсли;
Источники = Новый Массив;
Источники.Добавить(ИсточникРасширенийКонфигурации.БазаДанных);
Источники.Добавить(ИсточникРасширенийКонфигурации.СеансАктивные);
Источники.Добавить(ИсточникРасширенийКонфигурации.СеансОтключенные);
Для Каждого Источник Из Источники Цикл
Расширения = РасширенияКонфигурации.Получить(, Источник);
Если ТипЗнч(Расширения) <> Тип("Массив") Тогда
ВызватьИсключение "Native список расширений должен иметь тип Массив";
КонецЕсли;
Если Расширения.Количество() <> 0 Тогда
ВызватьИсключение "В своём новом стенде нет расширений базы или сеанса";
КонецЕсли;
КонецЦикла;
Если ТранзакцияАктивна() Тогда
ВызватьИсключение "Чужая или вложенная активная транзакция не допускается";
КонецЕсли;
КонецПроцедурыРазбор по шагам
В реальную Принять85(Запрос) платформа передает HTTPСервисЗапрос. Конструктора у этого типа нет. Guard собственной конфигурации и единственногоUUIDпользователя выполняется до чтения входного тела; nativeRequest.HTTPМетод обязан бытьPOST.
ReadonlyБазовыйURL проверяется только на две подготовленные формы своего loopbackendpoint, Host на127.0.0.1:18086, headerUUID на реальный UUID авторизованного пользователя. Заголовки — ФиксированноеСоответствие, не изменяемый список. Имена header сравниваются без учета регистра и дубликат не принимается.
ReadonlyПараметрыURL содержат только session из шаблона /lab/{session}, а ПараметрыЗапроса — только mode изquery. Это разные источники. ОтносительныйURL должен совпасть со своим путем; дополнительный route/query не принимается.
Content-Type=text/plain;charset=utf-8 и Content-Length обязательны для своего небольшого известного тела. Размер сравнивается с заранее сформированными ожидаемыми UTF-8-байтами, не с количеством символов русского текста. Web-server ограничение4096 должно действовать ДО handler: одна проверка header не защищает от уже принятого огромного/misdeclared тела.
mode=text вызывает ПолучитьТелоКакСтроку("UTF-8") и сравнивает весь собственный текст. Кодировка указана явно; установка body в клиенте и Content-Type заголовок — разные операции.
mode=bytes получает настоящие ДвоичныеДанные, сравнивает реальный размер и точные bytes черезBase64 только в памяти. Base64 не используется как шифрование/авторизация и не выводится в лог.
mode=stream использует настоящий nativeПоток тела, один буфер128 и loop по фактически прочитанному числу байтов. Читаются только фактические байты, короткие чтения не выдаются заEOF. Размер() потока не вызывается, seekability не предполагается; превышение/обрыв/несовпадение отказаны. Поток закрывается и на успехе, и на исключении.
Положительный Ответ создается HTTPСервисОтвет(200,,headers), текст включает свой UUID/реальныйmode/учебную карточку. Обработчик обязан вернуть этот объект платформе; создание объекта само по себе не отправляет сетевой ответ.
mode=file записывает только собственное небольшое тело в новое GetTempFileName имя, проверяет отсутствие до записи, existence/размер после. SetBodyFilename выбирает источник; GetBodyFilename сверяет точно этот собственный путь. Чтение платформой будет позже, поэтому раннего удаления/закрытия файла вместо ответа нет.
Поддерживающий клиент передает четыре настоящих HTTPЗапроса в свое публикационное1СHTTPendpoint, не mock объектаЗапрос. Каждый ответ требует200, собственный headerUUID и полный текст выбранногоmode, в том числе file-body. Пароль очищается после результата/исключения и не логируется.
При отказе/ошибке handler возвращает только стандартный код405/404/411/413/400 и постоянный безопасный текст. Содержимое неизвестного запроса, пароль, серверные пути и stacktrace не отражаются наружу. Объекты базы не пишутся; файлы/запросы автором реально не выполнялись.
Как проверить результат
У своего правильного запроса HTTPMethod=POST, только route session и querymode, exactHost/headerUUID и knownbyte length. Неверный метод/path/UUID/добавочныйquery/header/type дает отказ до работы с body.
text/bytes/stream должны получить полностью одинаковые ownUTF8-байты Книги; обрыв, неверный BOM/кодировка/длина/содержимое не подтверждаются частичным успехом.
Stream branch закрывает поток при обоих исходах, не требуетseek/Размер(). Нулевое чтение —конец, короткое положительное чтение продолжается. Фактический итог обязан совпасть с ожидаемым размером.
File branch не перезаписывает существующий файл, точно связывает новый ownfilename сHTTPСервисОтвет и не удаляет его до delayed read. Свежий клиентский fileответ должен содержать тот же свой текст, не path/страницу ошибки.
Клиент дает четыре подтвержденных ответа200 либо конкретный отказ. Повтор commandНачат=true запрещен, password очищается, лог не содержитнеизвестныхbody/credentials/serverpaths.
Конфигурация, права, веб-публикация, requestLimits и реальное delayed file чтение здесь не были развернуты/запущены. Это отдельные ручные проверки только в собственной VM, не доказанные статическими тестами.
Ожидаемый результат
Все свойства/три метода настоящего HTTPСервисЗапрос разобраны в опубликованном своем handler, а file-body источникHTTPСервисОтвет привязан к конкретному новому собственному файлу с учетом delayedread. Четыре полных запроса клиента и критерии отказа/успеха включены.
На что обратить внимание
HTTPСервисЗапрос создается платформой только при входящем запросе собственного опубликованного сервиса; его нельзя заменить НовыйHTTPСервисЗапрос или произвольнойСтруктура. ReadonlyHeaders/URL/query не назначаются.
Собственный UUID в URL/header не является аутентификацией. Требуется реальная проверенная Basic-аутентификация своего внутреннего пользователя и права, плюс выделенная VM/loopback. PlainHTTPBasic недопустимы для production-паролей, а webserverHost/header могут быть подделаны без этой изоляции.
БазовыйURL и ОтносительныйURL — разные части, routeParameters и queryParameters тоже. Handler не склеивает пользовательский путь с именем локального файла. Любой иной публикационный формат требует проверки в своем стенде, не угадывания/расширения до любых сайтов.
Принимающий веб-сервер способен буферизоватьbody еще доhandler. Ограничить Content-Length внутри1С недостаточно против огромного/misdeclared/chunkedrequest; ownIIS/Apache лимит4096 обязателен. Этот урок не универсальный защищенный публичныйAPI.
Поток может отдаватькороткие чтения и не поддерживатьseek/Размер. СравниваютсятолькоПрочитано bytes;конец0 не равен любомукороткому чтению. В программе нет использованиянеинициализированногоконца128байтного буфера.
HTTPСервисОтвет file-source читается приформированииответа платформой, не вSetBodyFilename. Удалениевконцеhandlerсломалобыещеотправляемыйответ. Отложеннуюплатформеннуюочистку/actualfileoutput нужно проверять отдельно; новые резервныекопии/архивы не создаются.
ПриunknownHTTPрезультате file мог бытьсоздан, handler/requestвыполнен. Catch не делает cleanupчужих/широкихкаталогов и не возвращаетrawОшибка. Повторные/нагрузочные вызовы могут создаватьмалые файлы;положительныйопыт ограниченоднимownclientrun.
Server/client/module contexts иnative8.5.1.1343контракты сверяются статически. Подготовительныеmetadata/publication/auth/requestlimitоперации, отправкаHTTP и delayedresponse/filecleanup реальноне выполнялись. RuntimeVerifiedScenarios=0.
Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.