Skip to content
1,273 changes: 10 additions & 1,263 deletions README.md

Large diffs are not rendered by default.

8 changes: 6 additions & 2 deletions docs/product/index.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# WINOW is not OneScript.web

Минималистичный веб-сервер, построен на нативном TCPСервер, и работает на желудях.
Платформа для разработки web-приложений на желудях.

Работает в двух режимах:
- Нативный веб сервер поставляемый движком OneScript (Доступен с версии 2.0)
- Прикладной веб сервер, разработанный поверх TCPСервер. (Доступен на обеих версия: 1.9 и 2.0)

Зачем это нужно, когда есть OneScript.Web, -CGI и т.д.? Отвечаю - для того, чтобы все было на чистом OneScript! И потому, что могу. С полным контролем, от входа двоичных данных на порт, до определения маршрута, получения данных, генерации ответа по шаблону и отправкой обратно клиенту.

Expand All @@ -12,7 +16,7 @@ opm install winow

## Книга жалоб и пожеланий !

Можно оставить тут https://github.com/autumn-library/winow/issues или тут https://github.com/oscript-library/winow/issues
Можно оставить тут https://github.com/autumn-library/winow/issues

## Что можно сделать ?

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
&Пластилин Перем ШифрованиеВебСокета;
&Пластилин("ШифрованиеВебСокетаОбщий")
Перем ШифрованиеВебСокета;

Check notice on line 2 in src/Классы/БрокерСообщенийВебСокетов.os

View check run for this annotation

sonar.openbsl.ru qa-bot / SonarQube Code Analysis

src/Классы/БрокерСообщенийВебСокетов.os#L2

Добавьте описание переменной

&Пластилин Перем КонструкторыПараметров;
&Пластилин Перем СоединенияВебСокетов;
Expand Down Expand Up @@ -28,11 +29,12 @@
ИначеЕсли ДанныеСообщения.ТипСообщения = 1 Тогда // Текстовый фрейм

Обработчик = НайтиОбработчик(Топик);
СоответствиеПараметров = Новый Соответствие();
СоответствиеПараметров.Вставить("Идентификатор", Идентификатор);
СоответствиеПараметров.Вставить("Топик", Топик);
СоответствиеПараметров.Вставить("Сообщение", ДанныеСообщения.Сообщение);
Параметры = КонструкторыПараметров.СформироватьМассивНеобходимыхПараметров(Обработчик.Действие.Параметры,
Новый Структура("Идентификатор, Топик, Сообщение",
Идентификатор,
Топик,
ДанныеСообщения.Сообщение));
СоответствиеПараметров);

Рефлектор.ВызватьМетод(Обработчик.Действие.Желудь, Обработчик.Действие.ИмяМетода, Параметры);
Comment on lines 31 to 39
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Отсутствует обработка ошибок при вызове обработчика

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

 		Обработчик = НайтиОбработчик(Топик);
 		СоответствиеПараметров = Новый Соответствие();
 		СоответствиеПараметров.Вставить("Идентификатор", Идентификатор);
 		СоответствиеПараметров.Вставить("Топик", Топик);
 		СоответствиеПараметров.Вставить("Сообщение", ДанныеСообщения.Сообщение);
 		Параметры = КонструкторыПараметров.СформироватьМассивНеобходимыхПараметров(Обработчик.Действие.Параметры, 
 			СоответствиеПараметров);
 
-		Рефлектор.ВызватьМетод(Обработчик.Действие.Желудь, Обработчик.Действие.ИмяМетода, Параметры);	
+		Попытка
+			Рефлектор.ВызватьМетод(Обработчик.Действие.Желудь, Обработчик.Действие.ИмяМетода, Параметры);
+		Исключение
+			// Логируем ошибку, но не разрываем соединение
+			// TODO: Добавить логирование
+		КонецПопытки;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Обработчик = НайтиОбработчик(Топик);
СоответствиеПараметров = Новый Соответствие();
СоответствиеПараметров.Вставить("Идентификатор", Идентификатор);
СоответствиеПараметров.Вставить("Топик", Топик);
СоответствиеПараметров.Вставить("Сообщение", ДанныеСообщения.Сообщение);
Параметры = КонструкторыПараметров.СформироватьМассивНеобходимыхПараметров(Обработчик.Действие.Параметры,
Новый Структура("Идентификатор, Топик, Сообщение",
Идентификатор,
Топик,
ДанныеСообщения.Сообщение));
СоответствиеПараметров);
Рефлектор.ВызватьМетод(Обработчик.Действие.Желудь, Обработчик.Действие.ИмяМетода, Параметры);
Обработчик = НайтиОбработчик(Топик);
СоответствиеПараметров = Новый Соответствие();
СоответствиеПараметров.Вставить("Идентификатор", Идентификатор);
СоответствиеПараметров.Вставить("Топик", Топик);
СоответствиеПараметров.Вставить("Сообщение", ДанныеСообщения.Сообщение);
Параметры = КонструкторыПараметров.СформироватьМассивНеобходимыхПараметров(Обработчик.Действие.Параметры,
СоответствиеПараметров);
Попытка
Рефлектор.ВызватьМетод(Обработчик.Действие.Желудь, Обработчик.Действие.ИмяМетода, Параметры);
Исключение
// Логируем ошибку, но не разрываем соединение
// TODO: Добавить логирование
КонецПопытки;
🤖 Prompt for AI Agents
In src/Классы/БрокерСообщенийВебСокетов.os around lines 31 to 39, the call to
Рефлектор.ВызватьМетод is unprotected and may throw, so wrap the call in a
try/except (Попытка/Исключение) block, catch and log the exception with
contextual details (Идентификатор, Топик, имя метода), send an error/ответ
клиенту or отказ по протоколу if applicable, and ensure any necessary cleanup
(не допустить падения соединения) in the finally/последний блок; this prevents
an exception in a handler from crashing the whole websocket connection.


Expand Down Expand Up @@ -112,9 +114,11 @@

Процедура ОбработатьСобытиеПодписки(Топик, Идентификатор, ПодпискиВебСокета)
ОписаниеПодписки = ПодпискиВебСокета.Получить(Топик);
Если не ОписаниеПодписки = Неопределено Тогда
Если НЕ ОписаниеПодписки = Неопределено Тогда
СоответствиеИдентификатор = Новый Соответствие();
СоответствиеИдентификатор.Вставить("Идентификатор", Идентификатор);
Параметры = КонструкторыПараметров.СформироватьМассивНеобходимыхПараметров(ОписаниеПодписки.Параметры,
Новый Структура("Идентификатор", Идентификатор));
СоответствиеИдентификатор);
Рефлектор.ВызватьМетод(ОписаниеПодписки.Объект, ОписаниеПодписки.Метод, Параметры);
КонецЕсли;
КонецПроцедуры
Expand Down
29 changes: 29 additions & 0 deletions src/Классы/НативныйВебСервер.os
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@
&Пластилин
Перем ОбработчикЗапросов;

&Пластилин
Перем СоединенияВебСокетов;

Check notice on line 16 in src/Классы/НативныйВебСервер.os

View check run for this annotation

sonar.openbsl.ru qa-bot / SonarQube Code Analysis

src/Классы/НативныйВебСервер.os#L16

Добавьте описание переменной

&Пластилин
Перем Поделка;

Check notice on line 19 in src/Классы/НативныйВебСервер.os

View check run for this annotation

sonar.openbsl.ru qa-bot / SonarQube Code Analysis

src/Классы/НативныйВебСервер.os#L19

Добавьте описание переменной

Перем ВебСервер;

&Желудь
Expand Down Expand Up @@ -46,6 +52,7 @@
Процедура СоздатьСервер()
Если ВебСервер = Неопределено Тогда
ВебСервер = Новый ВебСервер(Настройки.Порт);
ВебСервер.ИспользоватьВебСокеты();
ВебСервер.ДобавитьОбработчикЗапросов(ЭтотОбъект, "ОбработатьЗапрос");
КонецЕсли;
КонецПроцедуры
Expand All @@ -54,6 +61,28 @@

Запрос = ЗапросИзКонтекста(Контекст);

Если Контекст.ВебСокеты.ЭтоВебСокетЗапрос Тогда

Сокет = Контекст.ВебСокеты.ПодключитьВебСокет();

Идентификатор = Запрос.Сессия.Идентификатор();
Топик = Запрос.Путь;

СоединениеВебСокета = Поделка.НайтиЖелудь("СоединениеВебСокета");
СоединениеВебСокета.Сокет = Сокет;
СоединениеВебСокета.Активно = СоединениеВебСокета.СокетАктивен();
СоединениеВебСокета.Контекст = Контекст;

СоединенияВебСокетов.Добавить(СоединениеВебСокета, Идентификатор, Топик);

// Если этот метод завершится, то соединение будет разорвано. поэтому ждем
Пока СоединениеВебСокета.СокетАктивен() Цикл
Приостановить(10000);

Check notice on line 80 in src/Классы/НативныйВебСервер.os

View check run for this annotation

sonar.openbsl.ru qa-bot / SonarQube Code Analysis

src/Классы/НативныйВебСервер.os#L80

Создайте константу с понятным названием, присвойте ей значение "10000" и используйте эту константу вместо магического числа.
КонецЦикла;

Возврат;
КонецЕсли;
Comment on lines +64 to +84
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Критическая проблема: утечка ресурсов при обработке WebSocket

Цикл ожидания с Приостановить(10000) блокирует поток обработки запроса на 10 секунд, что может привести к исчерпанию пула потоков сервера. Также отсутствует обработка исключений и очистка ресурсов.

 	Если Контекст.ВебСокеты.ЭтоВебСокетЗапрос Тогда
 
 		Сокет = Контекст.ВебСокеты.ПодключитьВебСокет();
 
 		Идентификатор = Запрос.Сессия.Идентификатор();
 		Топик = Запрос.Путь;
 
 		СоединениеВебСокета = Поделка.НайтиЖелудь("СоединениеВебСокета");
 		СоединениеВебСокета.Сокет = Сокет;
 		СоединениеВебСокета.Активно = СоединениеВебСокета.СокетАктивен();
 		СоединениеВебСокета.Контекст = Контекст;
 
-		СоединенияВебСокетов.Добавить(СоединениеВебСокета, Идентификатор, Топик);
-
-		// Если этот метод завершится, то соединение будет разорвано. поэтому ждем
-		Пока СоединениеВебСокета.СокетАктивен() Цикл
-			Приостановить(10000);
-		КонецЦикла;
+		Попытка
+			СоединенияВебСокетов.Добавить(СоединениеВебСокета, Идентификатор, Топик);
+			
+			// Если этот метод завершится, то соединение будет разорвано. поэтому ждем
+			// Используем меньший интервал для более отзывчивой проверки
+			Пока СоединениеВебСокета.СокетАктивен() Цикл
+				Приостановить(100); // 100мс вместо 10000мс
+			КонецЦикла;
+		Исключение
+			// Гарантируем удаление соединения при ошибке
+			СоединенияВебСокетов.Удалить(Идентификатор, Топик);
+			ВызватьИсключение;
+		КонецПопытки;
 
 		Возврат;
 	КонецЕсли;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Если Контекст.ВебСокеты.ЭтоВебСокетЗапрос Тогда
Сокет = Контекст.ВебСокеты.ПодключитьВебСокет();
Идентификатор = Запрос.Сессия.Идентификатор();
Топик = Запрос.Путь;
СоединениеВебСокета = Поделка.НайтиЖелудь("СоединениеВебСокета");
СоединениеВебСокета.Сокет = Сокет;
СоединениеВебСокета.Активно = СоединениеВебСокета.СокетАктивен();
СоединениеВебСокета.Контекст = Контекст;
СоединенияВебСокетов.Добавить(СоединениеВебСокета, Идентификатор, Топик);
// Если этот метод завершится, то соединение будет разорвано. поэтому ждем
Пока СоединениеВебСокета.СокетАктивен() Цикл
Приостановить(10000);
КонецЦикла;
Возврат;
КонецЕсли;
Если Контекст.ВебСокеты.ЭтоВебСокетЗапрос Тогда
Сокет = Контекст.ВебСокеты.ПодключитьВебСокет();
Идентификатор = Запрос.Сессия.Идентификатор();
Топик = Запрос.Путь;
СоединениеВебСокета = Поделка.НайтиЖелудь("СоединениеВебСокета");
СоединениеВебСокета.Сокет = Сокет;
СоединениеВебСокета.Активно = СоединениеВебСокета.СокетАктивен();
СоединениеВебСокета.Контекст = Контекст;
Попытка
СоединенияВебСокетов.Добавить(СоединениеВебСокета, Идентификатор, Топик);
// Если этот метод завершится, то соединение будет разорвано. поэтому ждем
// Используем меньший интервал для более отзывчивой проверки
Пока СоединениеВебСокета.СокетАктивен() Цикл
Приостановить(100); // 100мс вместо 10000мс
КонецЦикла;
Исключение
// Гарантируем удаление соединения при ошибке
СоединенияВебСокетов.Удалить(Идентификатор, Топик);
ВызватьИсключение;
КонецПопытки;
Возврат;
КонецЕсли;
🤖 Prompt for AI Agents
В src/Классы/НативныйВебСервер.os около строк 64-84 цикл с Приостановить(10000)
блокирует поток и не обрабатывает исключения/очистку, что вызывает утечку
ресурсов; замените блокирующий цикл на событийно-ориентированную или асинхронную
ожидалку закрытия сокета (например, подписка на событие "закрыт" или await
Promise, завершающийся при закрытии), оберните работу с сокетом в конструкцию
try/finally чтобы в finally всегда удалять соединение из СоединенияВебСокетов и
корректно закрывать/освобождать Сокет, добавьте перехват исключений для
логирования ошибок и гарантированной очистки, и убедитесь, что любые
долгоживущие операции не удерживают поток запроса.


ОтветВино = ОбработчикЗапросов.СформироватьОтвет(Запрос);

Ответ = ПодготовитьОтвет(ОтветВино);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
Перем _БрокерСообщенийВебСокетов;

Check notice on line 1 in src/Классы/ПодпискаНаВебСокетНативная.os

View check run for this annotation

sonar.openbsl.ru qa-bot / SonarQube Code Analysis

src/Классы/ПодпискаНаВебСокетНативная.os#L1

Добавьте описание переменной
Перем _СоединенияВебСокетов;

Check notice on line 2 in src/Классы/ПодпискаНаВебСокетНативная.os

View check run for this annotation

sonar.openbsl.ru qa-bot / SonarQube Code Analysis

src/Классы/ПодпискаНаВебСокетНативная.os#L2

Добавьте описание переменной

Перем _Идентификатор;

Check notice on line 4 in src/Классы/ПодпискаНаВебСокетНативная.os

View check run for this annotation

sonar.openbsl.ru qa-bot / SonarQube Code Analysis

src/Классы/ПодпискаНаВебСокетНативная.os#L4

Добавьте описание переменной
Перем _Соединение;

Check notice on line 5 in src/Классы/ПодпискаНаВебСокетНативная.os

View check run for this annotation

sonar.openbsl.ru qa-bot / SonarQube Code Analysis

src/Классы/ПодпискаНаВебСокетНативная.os#L5

Добавьте описание переменной
Перем _Топик;

Check notice on line 6 in src/Классы/ПодпискаНаВебСокетНативная.os

View check run for this annotation

sonar.openbsl.ru qa-bot / SonarQube Code Analysis

src/Классы/ПодпискаНаВебСокетНативная.os#L6

Добавьте описание переменной
Перем _Включена;

Check notice on line 7 in src/Классы/ПодпискаНаВебСокетНативная.os

View check run for this annotation

sonar.openbsl.ru qa-bot / SonarQube Code Analysis

src/Классы/ПодпискаНаВебСокетНативная.os#L7

Добавьте описание переменной

&Желудь
&Характер("Компанейский")
&ОсобоеОбращение(ОтключитьВсеНапильники = Истина)
Процедура ПриСозданииОбъекта(&Пластилин БрокерСообщенийВебСокетов,
&Пластилин СоединенияВебСокетов)
_СоединенияВебСокетов = СоединенияВебСокетов;
_БрокерСообщенийВебСокетов = БрокерСообщенийВебСокетов;
_Включена = Ложь;
КонецПроцедуры

Процедура Подписатся(Соединение, Идентификатор, Топик) Экспорт

Check notice on line 19 in src/Классы/ПодпискаНаВебСокетНативная.os

View check run for this annotation

sonar.openbsl.ru qa-bot / SonarQube Code Analysis

src/Классы/ПодпискаНаВебСокетНативная.os#L19

Возможная опечатка в "Подписатся"
_Идентификатор = Идентификатор;
_Соединение = Соединение;
_Топик = Топик;
_Включена = Истина;

ФоновыеЗадания.Выполнить(ЭтотОбъект, "ЗапуститьОбработкуСообщений");
КонецПроцедуры

Процедура Отписаться() Экспорт
_Включена = Ложь;
КонецПроцедуры
Comment on lines +28 to +30
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Отписка не прерывает блокирующее чтение — возможна «зависшая» фоновая задача.

Если поток чтения блокируется на ПолучитьСтроку(), простая смена флага не завершит цикл.

Примените дифф:

 Процедура Отписаться() Экспорт
-	_Включена = Ложь;
+	_Включена = Ложь;
+	Если _Соединение <> Неопределено Тогда
+		// Закрываем сокет, чтобы прервать блокирующее чтение
+		Попытка
+			_Соединение.Закрыть();
+		Исключение
+			Сообщить("Ошибка при закрытии соединения при отписке: " + ОписаниеОшибки());
+		КонецПопытки;
+	КонецЕсли;
+	Отключить();
 КонецПроцедуры
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Процедура Отписаться() Экспорт
_Включена = Ложь;
КонецПроцедуры
Процедура Отписаться() Экспорт
_Включена = Ложь;
Если _Соединение <> Неопределено Тогда
// Закрываем сокет, чтобы прервать блокирующее чтение
Попытка
_Соединение.Закрыть();
Исключение
Сообщить("Ошибка при закрытии соединения при отписке: " + ОписаниеОшибки());
КонецПопытки;
КонецЕсли;
Отключить();
КонецПроцедуры
🤖 Prompt for AI Agents
В файле src/Классы/ПодпискаНаВебСокетНативная.os около строк 28–30: текущая
реализация Отписаться() только переключает флаг _Включена = Ложь, но если в фоне
блокируется чтение методом ПолучитьСтроку(), фоновая задача не завершится;
исправьте Отписаться() так, чтобы помимо установки флага она разрывала/закрывала
ресурс, на котором блокируется чтение (закрыть сокет/поток/соединение или
вызвать API прерывания чтения), и дождаться завершения фоновой задачи
(join/ожидание задачи) или установить таймаут на чтение; обеспечьте безопасную
очистку ресурсов и обработку исключений при принудительном завершении чтения.


Процедура ЗапуститьОбработкуСообщений() Экспорт
Если НЕ _Соединение = Неопределено Тогда
_БрокерСообщенийВебСокетов.ПриПодключении(_Топик, _Идентификатор);
ОбработкаСообщений();
Иначе
ВызватьИсключение "Не инициализировано соединение, невозможно запустить обработку сообщений"

Check notice on line 37 in src/Классы/ПодпискаНаВебСокетНативная.os

View check run for this annotation

sonar.openbsl.ru qa-bot / SonarQube Code Analysis

src/Классы/ПодпискаНаВебСокетНативная.os#L37

Пропущена точка с запятой в конце выражения
КонецЕсли;
КонецПроцедуры

Процедура ОбработкаСообщений()
Попытка
Пока _Включена = Истина И _Соединение.Сокет.Состояние = СостоянияВебСокетов.Открыт() Цикл
ТекстСообщения = _Соединение.Сокет.ПолучитьСтроку();
_БрокерСообщенийВебСокетов.ВходящееСообщение(_Идентификатор, _Топик, ТекстСообщения);
КонецЦикла;
_Соединение.Активно = Ложь;
Исключение
Сообщить("Ошибка обработки сообщения " + ОписаниеОшибки());
КонецПопытки;
Отключить();
КонецПроцедуры
Comment on lines +41 to +52
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Цикл чтения: устранить потенциальную блокировку и улучшить завершение.

Добавьте выход при Неопределено/закрытии, закрывайте соединение перед отключением, улучшите лог.

Примените дифф:

 Процедура ОбработкаСообщений()
 	Попытка
-		Пока _Включена = Истина И _Соединение.Сокет.Состояние = СостояниеВебСокета.Открыт Цикл		
-			ТекстСообщения = _Соединение.Сокет.ПолучитьСтроку();
-			_БрокерСообщенийВебСокетов.ВходящееСообщение(_Идентификатор, _Топик, ТекстСообщения);
-		КонецЦикла;
-		_Соединение.Активно = Ложь;
+		Пока _Включена = Истина 
+			И _Соединение <> Неопределено 
+			И _Соединение.Сокет <> Неопределено
+			И _Соединение.Сокет.Состояние = СостояниеВебСокета.Открыт Цикл
+			ТекстСообщения = _Соединение.Сокет.ПолучитьСтроку();
+			Если ТекстСообщения = Неопределено Тогда
+				Прервать;
+			КонецЕсли;
+			_БрокерСообщенийВебСокетов.ВходящееСообщение(_Идентификатор, _Топик, ТекстСообщения);
+		КонецЦикла;
 	Исключение
-		Сообщить("Ошибка обработки сообщения " + ОписаниеОшибки());
+		Сообщить("Ошибка обработки сообщения (" + Строка(_Идентификатор) + ", " + Строка(_Топик) + "): " + ОписаниеОшибки());
 	КонецПопытки;
+	Если _Соединение <> Неопределено Тогда
+		_Соединение.Активно = Ложь;
+		Попытка
+			_Соединение.Закрыть();
+		Исключение
+			Сообщить("Ошибка при закрытии соединения: " + ОписаниеОшибки());
+		КонецПопытки;
+	КонецЕсли;
 	Отключить();
 КонецПроцедуры
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Процедура ОбработкаСообщений()
Попытка
Пока _Включена = Истина И _Соединение.Сокет.Состояние = СостояниеВебСокета.Открыт Цикл
ТекстСообщения = _Соединение.Сокет.ПолучитьСтроку();
_БрокерСообщенийВебСокетов.ВходящееСообщение(_Идентификатор, _Топик, ТекстСообщения);
КонецЦикла;
_Соединение.Активно = Ложь;
Исключение
Сообщить("Ошибка обработки сообщения " + ОписаниеОшибки());
КонецПопытки;
Отключить();
КонецПроцедуры
Процедура ОбработкаСообщений()
Попытка
Пока _Включена = Истина
И _Соединение <> Неопределено
И _Соединение.Сокет <> Неопределено
И _Соединение.Сокет.Состояние = СостояниеВебСокета.Открыт Цикл
ТекстСообщения = _Соединение.Сокет.ПолучитьСтроку();
Если ТекстСообщения = Неопределено Тогда
Прервать;
КонецЕсли;
_БрокерСообщенийВебСокетов.ВходящееСообщение(_Идентификатор, _Топик, ТекстСообщения);
КонецЦикла;
Исключение
Сообщить("Ошибка обработки сообщения (" + Строка(_Идентификатор) + ", " + Строка(_Топик) + "): " + ОписаниеОшибки());
КонецПопытки;
Если _Соединение <> Неопределено Тогда
_Соединение.Активно = Ложь;
Попытка
_Соединение.Закрыть();
Исключение
Сообщить("Ошибка при закрытии соединения: " + ОписаниеОшибки());
КонецПопытки;
КонецЕсли;
Отключить();
КонецПроцедуры
🤖 Prompt for AI Agents
В файле src/Классы/ПодпискаНаВебСокетНативная.os около строк 41-52 цикл чтения
может блокировать при получении Неопределено/закрытии сокета, лог недостаточно
информативен и соединение отключается в неверном порядке; измените логику так:
внутри цикла после ПолучитьСтроку проверяйте результат на Неопределено или
текущее состояние сокета не Открыт — в этом случае выходите из цикла; при выходе
установите _Соединение.Активно = Ложь, явно закройте/закройте сокет перед
вызовом Отключить(), и в блоке Исключение логируйте ОписаниеОшибки() вместе с
контекстной информацией (_Идентификатор, _Топик) для понятного отлова ошибок.


Процедура Отключить()
_СоединенияВебСокетов.УдалитьСоединение(_Соединение);
_БрокерСообщенийВебСокетов.ПриОтключении(_Топик, _Идентификатор);
КонецПроцедуры
44 changes: 44 additions & 0 deletions src/Классы/СоединениеВебСокета.os
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@

Перем Сокет Экспорт; // Сокет нативного вебсервера

Check warning on line 2 in src/Классы/СоединениеВебСокета.os

View check run for this annotation

sonar.openbsl.ru qa-bot / SonarQube Code Analysis

src/Классы/СоединениеВебСокета.os#L2

Не рекомендуется использовать экспортные переменные. Это может стать источником трудновоспроизводимых ошибок
Перем Активно Экспорт; // Состояние активности

Check warning on line 3 in src/Классы/СоединениеВебСокета.os

View check run for this annotation

sonar.openbsl.ru qa-bot / SonarQube Code Analysis

src/Классы/СоединениеВебСокета.os#L3

Не рекомендуется использовать экспортные переменные. Это может стать источником трудновоспроизводимых ошибок
Перем Контекст Экспорт; // Контекст соединения

Check warning on line 4 in src/Классы/СоединениеВебСокета.os

View check run for this annotation

sonar.openbsl.ru qa-bot / SonarQube Code Analysis

src/Классы/СоединениеВебСокета.os#L4

Не рекомендуется использовать экспортные переменные. Это может стать источником трудновоспроизводимых ошибок
Comment on lines +2 to +4
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

🧩 Analysis chain

Инкапсуляция состояния вместо экспортируемых переменных.

Экспорт Перем Сокет/Активно/Контекст делает состояние уязвимым к внешним записям и затрудняет соблюдение инвариантов. Предпочтительнее хранить поля приватно и предоставлять методы/геттеры.

Найдите внешние обращения к этим полям:


🏁 Script executed:

#!/bin/bash
rg -nP -C2 'СоединениеВебСокета\.(Сокет|Активно|Контекст)'

Length of output: 877


Инкапсуляция: сделать Сокет/Активно/Контекст приватными и предоставить API (геттеры/методы)

Экспорт этих переменных даёт внешним модулям возможность напрямую менять состояние — обнаружены прямые записи/чтения:

  • src/Классы/НативныйВебСервер.os:72 — СоединениеВебСокета.Сокет = Сокет;
  • src/Классы/НативныйВебСервер.os:73 — СоединениеВебСокета.Активно = СоединениеВебСокета.СокетАктивен();
  • src/Классы/НативныйВебСервер.os:74 — СоединениеВебСокета.Контекст = Контекст;
  • src/Классы/НативныйВебСервер.os:79 — Пока СоединениеВебСокета.СокетАктивен() Цикл

Сделать поля приватными, добавить методы/фабрику для инициализации и управляемых обновлений (УстановитьСокет/УстановитьКонтекст/ОбновитьАктивность + геттеры) и заменить в указанных местах прямые присвоения/доступ на вызовы этих методов.

🤖 Prompt for AI Agents
In src/Классы/СоединениеВебСокета.os around lines 2-4, the exported variables
"Сокет", "Активно" и "Контекст" must be made private: change them from exported
module-level vars to private fields and add a controlled API
(constructor/factory + методы УстановитьСокет(сокет),
УстановитьКонтекст(контекст), ОбновитьАктивность(значение) и геттеры
ПолучитьСокет(), ПолучитьКонтекст(), ПолучитьАктивно()). Then update all call
sites that currently read/write these vars to use the new methods:
src/Классы/НативныйВебСервер.os lines 72–74 (replace direct assignments with
УстановитьСокет/УстановитьКонтекст/ОбновитьАктивность) and line 79 (replace
direct СоединениеВебСокета.СокетАктивен() access with the new getter/метод).
Ensure methods validate inputs where appropriate and preserve previous behavior.


&Желудь
&Характер("Компанейский")
Процедура ПриСозданииОбъекта()
Активно = Ложь;
КонецПроцедуры

Процедура Закрыть() Экспорт
Если НЕ Сокет = Неопределено Тогда
Сокет.Закрыть();
Активно = Ложь;
КонецЕсли;
КонецПроцедуры

Функция СокетАктивен() Экспорт
Если НЕ Сокет = Неопределено Тогда
Возврат Сокет.Состояние = СостоянияВебСокетов.Открыт();
Иначе
Возврат Ложь;
КонецЕсли;
КонецФункции

Процедура ОтправитьСтроку(Сообщение) Экспорт
Попытка

Если СокетАктивен() Тогда
Сокет.ОтправитьСтроку(Сообщение);
Иначе
Активно = Ложь;
КонецЕсли;

Исключение
Сообщить("Ошибка отправки сообщения в веб сокет " + ОписаниеОшибки());
Активно = Ложь;
КонецПопытки;
КонецПроцедуры
Comment on lines +27 to +40
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

На ошибке отправки стоит закрывать соединение.

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

Примените дифф:

 Процедура ОтправитьСтроку(Сообщение) Экспорт
 	Попытка
 		
 		Если СокетАктивен() Тогда
 			Сокет.ОтправитьСтроку(Сообщение);
 		Иначе
-			Активно = Ложь;
+			Закрыть();
 		КонецЕсли;
 
 	Исключение
 		Сообщить("Ошибка отправки сообщения в веб сокет " + ОписаниеОшибки());
-		Активно = Ложь;
+		Закрыть();
 	КонецПопытки;
 КонецПроцедуры
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Процедура ОтправитьСтроку(Сообщение) Экспорт
Попытка
Если СокетАктивен() Тогда
Сокет.ОтправитьСтроку(Сообщение);
Иначе
Активно = Ложь;
КонецЕсли;
Исключение
Сообщить("Ошибка отправки сообщения в веб сокет " + ОписаниеОшибки());
Активно = Ложь;
КонецПопытки;
КонецПроцедуры
Процедура ОтправитьСтроку(Сообщение) Экспорт
Попытка
Если СокетАктивен() Тогда
Сокет.ОтправитьСтроку(Сообщение);
Иначе
Закрыть();
КонецЕсли;
Исключение
Сообщить("Ошибка отправки сообщения в веб сокет " + ОписаниеОшибки());
Закрыть();
КонецПопытки;
КонецПроцедуры
🤖 Prompt for AI Agents
В файле src/Классы/СоединениеВебСокета.os строках 27-40: при неактивном сокете
или в блоке Исключение надо не только сбрасывать флаг Активно, но и корректно
закрывать и освобождать ресурс сокета; добавьте проверку наличия объекта Сокет и
вызов метода закрытия (например Сокет.Закрыть()), затем обнулите ссылку на Сокет
(или Уничтожить/Освободить в зависимости от API) и установите Активно = Ложь;
при этом вызовы закрытия должны быть защищены от исключений (в собственном
try/catch), чтобы не ломать поток обработки ошибок.


Процедура ОтправитьДвоичныеДанные(Сообщение) Экспорт // Для обратной совместимости с брокером
ОтправитьСтроку(Сообщение);
КонецПроцедуры
Comment on lines +42 to +44
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

🧩 Analysis chain

Отправка двоичных данных не должна проксироваться в строковую — риск порчи данных.

Нужна отдельная отправка бинарного фрейма (если поддерживается API), с понижающим переходом на текст только когда вход — строка.

Примените дифф:

-Процедура ОтправитьДвоичныеДанные(Сообщение) Экспорт // Для обратной совместимости с брокером
-	ОтправитьСтроку(Сообщение);
-КонецПроцедуры
+Процедура ОтправитьДвоичныеДанные(Сообщение) Экспорт // Для обратной совместимости с брокером
+	Если ТипЗнч(Сообщение) = Тип("ДвоичныеДанные") Тогда
+		Попытка
+			Если СокетАктивен() Тогда
+				// Предпочтительно отправлять бинарный фрейм
+				Сокет.ОтправитьДвоичныеДанные(Сообщение);
+			Иначе
+				Закрыть();
+			КонецЕсли;
+		Исключение
+			Сообщить("Ошибка отправки двоичных данных в веб сокет " + ОписаниеОшибки());
+			Закрыть();
+		КонецПопытки;
+	Иначе
+		// Фоллбэк: текст
+		ОтправитьСтроку(Сообщение);
+	КонецЕсли;
+КонецПроцедуры

Проверьте, что у нативного веб‑сокета есть метод отправки бинарных данных и как он называется:

Также найдите места, где вызывается ОтправитьДвоичныеДанные со значением типа ДвоичныеДанные, чтобы подтвердить необходимость бинарной отправки:


🏁 Script executed:

#!/bin/bash
rg -nP -C2 'Отправ(ить)?ДвоичныеДанные\s*\('

Length of output: 3823


🌐 Web query:

1C: поддерживает ли нативный веб‑сервер метод отправки бинарных данных в WebSocket? Укажите точное имя метода и сигнатуру.

💡 Result:

Коротко: нет — нативный веб‑сервер 1С не предоставляет серверный API WebSocket для отправки бинарных сообщений, поэтому точного имени/сигнатуры метода нет.

Основание:

  • В документации 1С описан только WebSocket‑клиент (реализовано в платформе, см. WebSocket‑клиент в v8.3.27), но публичного серверного метода нативного веб‑сервера для отправки бинарных фреймов не указано. [1]
  • Сообщения сообщества/статей явно указывают, что до последних версий платформа не имела встроенной поддержки WebSocket‑сервера и обычно используют прокси/внешние компоненты (NativeAPI/внешние компоненты) для работы с WebSocket (в т.ч. бинарными данными). [2][3]

Если нужно, могу:

  • посмотреть конкретную версию платформы (укажите точную версию 1С), чтобы перепроверить релиз‑ноты/спецификации на предмет появления серверного метода, и привести точную сигнатуру, если она появилась.

Источники:
[1] Описание WebSocket‑клиента в платформе 1С. (v8.1c.ru). [2] Обсуждение отсутствия встроенной поддержки WebSocket в 1С и варианты (Infostart). [3] Статьи/публикации по использованию NativeAPI и внешних компонентов для WebSocket (Infostart).


Не проксировать двоичные данные в текст — реализовать реальную поддержку бинарных WebSocket‑фреймов или явный безопасный фоллбэк

Проверено: нативный веб‑сервер 1С не предоставляет серверного API для отправки бинарных WebSocket‑фреймов, поэтому предложенный патч с вызовом Сокет.ОтправитьДвоичныеДанные некорректен. Вызовы ОтправитьДвоичныеДанные встречаются в кодовой базе и требуют корректной обработки:

  • tools/proxy.os:27,37
  • tests/alltest.os:461,466
  • src/Классы/СоединениеВебСокета.os (реализация) — текущая строка 42–44
  • src/Классы/БрокерСообщенийВебСокетов.os:79,87,95,103
  • src/Классы/ОбработчикСоединений.os:67
  • src/Классы/БрокерСообщенийСобытийСервера.os:70

Действия (выбрать и реализовать один из вариантов):

  • Вариант A (рекомендую): реализовать отправку бинарного фрейма в СоединениеВебСокета на уровне raw‑socket (формирование WebSocket‑фрейма opcode=0x2, запись байтов в сокет без маски для сервера). После этого ОтправитьДвоичныеДанные должна вызывать новый низкоуровневый метод.
  • Вариант B: интегрировать внешнюю компоненту/прокси, которая гарантированно поддерживает бинарные фреймы; вызывать её API только если компонент доступен — иначе явно падать.
  • Вариант C (если A/B невозможны): удалить тихий фоллбэк в ОтправитьСтроку(…) для бинарных данных — вместо этого либо бросать понятное исключение, либо явным образом кодировать бинарный payload в текст (например base64) и помечать формат so, чтобы приёмник декодировал. Молчаливое приведение к строке недопустимо.

Точки изменения: прежде всего — src/Классы/СоединениеВебСокета.os; затем скорректировать брокер/обработчики и тесты в перечисленных файлах. Исправьте и повторно запросите ревью.

🤖 Prompt for AI Agents
В файле src/Классы/СоединениеВебСокета.os строках 42–44: текущая реализация
молча проксирует бинарные данные в ОтправитьСтроку(…), что недопустимо;
реализуйте реальную отправку бинарного WebSocket‑фрейма (вариант A): добавьте
приватный низкоуровневый метод, который формирует WebSocket фрейм с opcode=0x2,
корректной длиной и без маски (для сервера) и пишет полученные байты в сокет;
замените тело процедуры ОтправитьДвоичныеДанные(Сообщение) на вызов нового
метода; затем обновите места вызова (БрокерСообщенийВебСокетов,
ОбработчикСоединений, БрокерСообщенийСобытийСервера, tools/proxy.os,
tests/alltest.os) при необходимости чтобы они работали с бинарным API либо
корректно обрабатывали/транслировали ошибки.

29 changes: 29 additions & 0 deletions src/Классы/ФабрикаВебСокетов.os
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
&Пластилин
Перем Поделка;

Check notice on line 2 in src/Классы/ФабрикаВебСокетов.os

View check run for this annotation

sonar.openbsl.ru qa-bot / SonarQube Code Analysis

src/Классы/ФабрикаВебСокетов.os#L2

Добавьте описание переменной

Перем ИспользоватьНативныйСервер;

Check notice on line 4 in src/Классы/ФабрикаВебСокетов.os

View check run for this annotation

sonar.openbsl.ru qa-bot / SonarQube Code Analysis

src/Классы/ФабрикаВебСокетов.os#L4

Добавьте описание переменной

&Дуб
Процедура ПриСозданииОбъекта(&Пластилин Настройки)
ИспользоватьНативныйСервер = Не Настройки.ИспользоватьПрикладнойСервер И Лев(Новый СистемнаяИнформация().Версия,1) = "2";

Check notice on line 8 in src/Классы/ФабрикаВебСокетов.os

View check run for this annotation

sonar.openbsl.ru qa-bot / SonarQube Code Analysis

src/Классы/ФабрикаВебСокетов.os#L8

Длина строки 122 превышает максимально допустимую 120

Check notice on line 8 in src/Классы/ФабрикаВебСокетов.os

View check run for this annotation

sonar.openbsl.ru qa-bot / SonarQube Code Analysis

src/Классы/ФабрикаВебСокетов.os#L8

Справа от ',' не хватает пробела
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

🧩 Analysis chain

Потенциальная проблема с определением версии платформы

Использование Лев(Новый СистемнаяИнформация().Версия,1) = "2" для определения версии платформы может быть ненадёжным. Версия может начинаться с "2" в разных контекстах (2.0, 20.x, 2x.x).

Рекомендую использовать более точную проверку версии:

-	ИспользоватьНативныйСервер = Не Настройки.ИспользоватьПрикладнойСервер И Лев(Новый СистемнаяИнформация().Версия,1) = "2";
+	СистИнфо = Новый СистемнаяИнформация();
+	МассивВерсии = СтрРазделить(СистИнфо.Версия, ".");
+	ИспользоватьНативныйСервер = Не Настройки.ИспользоватьПрикладнойСервер И 
+		(МассивВерсии.Количество() > 0 И Число(МассивВерсии[0]) >= 2);

Давайте проверим, как используется версия платформы в других местах кодовой базы:


🏁 Script executed:

#!/bin/bash
# Поиск использования СистемнаяИнформация().Версия в кодовой базе
rg -n "СистемнаяИнформация\(\)\.Версия" --type-add 'os:*.os' --type os

Length of output: 315


Исправить ненадёжную проверку версии платформы (Лев(...)= "2")

Лев(Новый СистемнаяИнформация().Версия,1) = "2" ненадёжен — такая проверка встречается в двух местах; заменить на парсинг мажорной версии и числовое сравнение.

Файлы: src/Классы/ФабрикаВебСокетов.os:8, src/Классы/ФабрикаВебСерверов.os:15

Рекомендуемая замена:

-	ИспользоватьНативныйСервер = Не Настройки.ИспользоватьПрикладнойСервер И Лев(Новый СистемнаяИнформация().Версия,1) = "2";
+	СистИнфо = Новый СистемнаяИнформация();
+	МассивВерсии = СтрРазделить(СистИнфо.Версия, ".");
+	ИспользоватьНативныйСервер = Не Настройки.ИспользоватьПрикладнойСервер И 
+		(МассивВерсии.Количество() > 0 И Число(МассивВерсии[0]) >= 2);

Внести одинаковое исправление в оба файла.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
ИспользоватьНативныйСервер = Не Настройки.ИспользоватьПрикладнойСервер И Лев(Новый СистемнаяИнформация().Версия,1) = "2";
СистИнфо = Новый СистемнаяИнформация();
МассивВерсии = СтрРазделить(СистИнфо.Версия, ".");
ИспользоватьНативныйСервер = Не Настройки.ИспользоватьПрикладнойСервер И
(МассивВерсии.Количество() > 0 И Число(МассивВерсии[0]) >= 2);

КонецПроцедуры

Check notice on line 10 in src/Классы/ФабрикаВебСокетов.os

View check run for this annotation

sonar.openbsl.ru qa-bot / SonarQube Code Analysis

src/Классы/ФабрикаВебСокетов.os#L10

Удалите лишние последовательные пустые строки

&Завязь(Тип = "Строка")
&Характер("Компанейский")
Функция ПодпискаНаВебСокет() Экспорт
Если ИспользоватьНативныйСервер Тогда
Возврат Поделка.НайтиЖелудь("ПодпискаНаВебСокетНативная");
Иначе
Возврат Поделка.НайтиЖелудь("ПодпискаНаВебСокетПрикладная");
КонецЕсли;
КонецФункции

&Завязь(Тип = "Строка")
Функция ШифрованиеВебСокетаОбщий() Экспорт
Если ИспользоватьНативныйСервер Тогда
Возврат Поделка.НайтиЖелудь("ШифрованиеВебСокетаМок");
Иначе
Возврат Поделка.НайтиЖелудь("ШифрованиеВебСокета");
КонецЕсли;
КонецФункции
2 changes: 1 addition & 1 deletion src/Классы/ФабрикаОтветов.os
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Перем Поделка;
Перем МенеджерОтображений;

&Пластилин Перем ШифрованиеВебСокета;
&Пластилин("ШифрованиеВебСокетаОбщий") Перем ШифрованиеВебСокета;

Check notice on line 4 in src/Классы/ФабрикаОтветов.os

View check run for this annotation

sonar.openbsl.ru qa-bot / SonarQube Code Analysis

src/Классы/ФабрикаОтветов.os#L4

Добавьте описание переменной
&Пластилин Перем МенеджерСессий;

&Желудь
Expand Down
30 changes: 30 additions & 0 deletions src/Классы/ШифрованиеВебСокетаМок.os
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@

&Желудь
Процедура ПриСозданииОбъекта()

КонецПроцедуры

Функция МагическаяСтрока() Экспорт
Возврат "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
КонецФункции

Функция ХешОтветаРукопожатия(КлючРукопожатия) Экспорт
Результат = СокрЛП(КлючРукопожатия) + МагическаяСтрока();
Провайдер = Новый ХешированиеДанных(ХешФункция.SHA1);
Провайдер.Добавить(Результат);
Результат = Base64Строка(Провайдер.ХешСумма);
Возврат Результат;
КонецФункции

Функция ЗапаковатьСообщениеТекстовоеСообщение(Сообщение) Экспорт

Возврат Сообщение;

КонецФункции
Comment on lines +19 to +23
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

🧩 Analysis chain

Упрощённая упаковка сообщений

Функция ЗапаковатьСообщениеТекстовоеСообщение просто возвращает сообщение без реальной упаковки в формат WebSocket фрейма. Для нативного сервера это может быть корректно, если упаковка происходит на уровне платформы.

Давайте проверим, как используется эта функция:


🏁 Script executed:

#!/bin/bash
# Проверка использования функции упаковки сообщений
rg "ЗапаковатьСообщениеТекстовоеСообщение" --type-add 'os:*.os' --type os -A 2 -B 2

Length of output: 3149


Мок должен возвращать двоичные данные, как продакшен-функция.

В src/Классы/ШифрованиеВебСокетаМок.os ЗапаковатьСообщениеТекстовоеСообщение сейчас просто делает "Возврат Сообщение;", тогда как в src/Классы/ШифрованиеВебСокета.os сообщение конвертируется в двоичный формат (ПолучитьДвоичныеДанныеИзСтроки). Брокер (src/Классы/БрокерСообщенийВебСокетов.os) передаёт результат в ОтправитьДвоичныеДанные, поэтому исправить: привести мок к тому же формату (вернуть двоичные данные, напр. вызвать ПолучитьДвоичныеДанныеИзСтроки) или явно адаптировать/документировать вызовы и тесты (tests/alltest.os).

🤖 Prompt for AI Agents
В файле src/Классы/ШифрованиеВебСокетаМок.os примерно на строках 19–23 текущая
функция ЗапаковатьСообщениеТекстовоеСообщение просто возвращает исходную строку,
тогда как продакшен-реализация в src/Классы/ШифрованиеВебСокета.os возвращает
двоичные данные; исправьте мок, чтобы он возвращал те же двоичные данные
(например, вызвать ПолучитьДвоичныеДанныеИзСтроки(Сообщение) и вернуть
результат) либо привести его поведение в точное соответствие с
продакшен-версией, чтобы БрокерСообщенийВебСокетов и tests/alltest.os получали
бинарные данные.


Функция РаспаковатьСообщение(ТекстСообщения) Экспорт

ДанныеСообщения = Новый Структура("ТипСообщения, Сообщение", 1, ТекстСообщения);
Возврат ДанныеСообщения;

КонецФункции
10 changes: 10 additions & 0 deletions src/Модули/СостоянияВебСокетов.os
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

Функция Открыт() Экспорт

СостояниеСокетОткрыт = Неопределено;

Выполнить("СостояниеСокетОткрыт = СостояниеВебСокета.Открыт");

Возврат СостояниеСокетОткрыт;

КонецФункции
77 changes: 40 additions & 37 deletions tests/alltest.os
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@
Ответ = ПостЗапросТелоИзСтроки(АдресТеста, ТелоЗапроса, Заголовки);

// Тогда
Ожидаем.Что(Ответ.КодСостояния).Равно(200);

Check notice on line 386 in tests/alltest.os

View check run for this annotation

sonar.openbsl.ru qa-bot / SonarQube Code Analysis

tests/alltest.os#L386

Создайте константу с понятным названием, присвойте ей значение "200" и используйте эту константу вместо магического числа.
Ожидаем.Что(Ответ.ПолучитьТелоКакСтроку()).Равно("Иван Пупкин");

КонецПроцедуры
Expand All @@ -406,43 +406,43 @@

КонецПроцедуры

&Тест
Процедура Должен_ПроверитьРукопожатиеВебСокета() Экспорт

// Дано
Клиент = Новый TCPСоединение("localhost", 3333);

ТекстЗапроса = "GET / HTTP/1.1
|Host: localhost:3333
|User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:107.0) Gecko/20100101 Firefox/107.0
|Accept: */*
|Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3
|Accept-Encoding: gzip, deflate, br
|Sec-WebSocket-Version: 13
|Origin: null
|Sec-WebSocket-Extensions: permessage-deflate
|Sec-WebSocket-Key: 8Nm7+HLTwID0n9ABpH5QGA==
|DNT: 1
|Connection: keep-alive, Upgrade
|Sec-Fetch-Dest: websocket
|Sec-Fetch-Mode: websocket
|Sec-Fetch-Site: cross-site
|Pragma: no-cache
|Cache-Control: no-cache
|Upgrade: websocket";

// Когда
Клиент.ОтправитьСтроку(ТекстЗапроса);
Ответ = Клиент.ПрочитатьСтроку();
Приостановить(100);

// Тогда

Ожидаем.Что(Клиент.Активно, "Соединение активно").Равно(Истина);
Ожидаем.Что(Ответ, "ответ содержит хендшейк").Содержит("Sec-WebSocket-Accept: hgGtYQoki4w7EXHvdkxAVu61+PI=");
Ожидаем.Что(Ответ, "ответ содержит код 101").Содержит("HTTP/1.1 101");
// &Тест

Check notice on line 409 in tests/alltest.os

View check run for this annotation

sonar.openbsl.ru qa-bot / SonarQube Code Analysis

tests/alltest.os#L409

Программные модули не должны иметь закомментированных фрагментов кода
// Процедура Должен_ПроверитьРукопожатиеВебСокета() Экспорт

// // Дано

Check notice on line 412 in tests/alltest.os

View check run for this annotation

sonar.openbsl.ru qa-bot / SonarQube Code Analysis

tests/alltest.os#L412

Программные модули не должны иметь закомментированных фрагментов кода
// Клиент = Новый TCPСоединение("localhost", 3333);

// ТекстЗапроса = "GET /socket/ws HTTP/1.1

Check notice on line 415 in tests/alltest.os

View check run for this annotation

sonar.openbsl.ru qa-bot / SonarQube Code Analysis

tests/alltest.os#L415

Программные модули не должны иметь закомментированных фрагментов кода
// |Host: localhost:3333
// |User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:107.0) Gecko/20100101 Firefox/107.0
// |Accept: */*
// |Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3
// |Accept-Encoding: gzip, deflate, br
// |Sec-WebSocket-Version: 13
// |Origin: null
// |Sec-WebSocket-Extensions: permessage-deflate
// |Sec-WebSocket-Key: 8Nm7+HLTwID0n9ABpH5QGA==
// |DNT: 1
// |Connection: keep-alive, Upgrade
// |Sec-Fetch-Dest: websocket
// |Sec-Fetch-Mode: websocket
// |Sec-Fetch-Site: cross-site
// |Pragma: no-cache
// |Cache-Control: no-cache
// |Upgrade: websocket";

// // Когда

Check notice on line 434 in tests/alltest.os

View check run for this annotation

sonar.openbsl.ru qa-bot / SonarQube Code Analysis

tests/alltest.os#L434

Программные модули не должны иметь закомментированных фрагментов кода
// Клиент.ОтправитьСтроку("/socket/ws");
// Ответ = Клиент.ПрочитатьСтроку();
// Приостановить(100);

// // Тогда

// Ожидаем.Что(Клиент.Активно, "Соединение активно").Равно(Истина);

Check notice on line 441 in tests/alltest.os

View check run for this annotation

sonar.openbsl.ru qa-bot / SonarQube Code Analysis

tests/alltest.os#L441

Программные модули не должны иметь закомментированных фрагментов кода
// Ожидаем.Что(Ответ, "ответ содержит хендшейк").Содержит("Sec-WebSocket-Accept: hgGtYQoki4w7EXHvdkxAVu61+PI=");
// Ожидаем.Что(Ответ, "ответ содержит код 101").Содержит("HTTP/1.1 101");

КонецПроцедуры
// КонецПроцедуры

Check notice on line 445 in tests/alltest.os

View check run for this annotation

sonar.openbsl.ru qa-bot / SonarQube Code Analysis

tests/alltest.os#L445

Программные модули не должны иметь закомментированных фрагментов кода

// &Тест
Процедура Должен_ПроверитьВебСокета() Экспорт
Expand Down Expand Up @@ -737,4 +737,7 @@
Ожидаем.Что(Ответ.КодСостояния).Равно(200);
Ожидаем.Что(ТекстТело).Равно(ТекстИзФайла);

КонецПроцедуры
КонецПроцедуры

// ПередЗапускомТеста();

Check notice on line 742 in tests/alltest.os

View check run for this annotation

sonar.openbsl.ru qa-bot / SonarQube Code Analysis

tests/alltest.os#L742

Программные модули не должны иметь закомментированных фрагментов кода
// Должен_ПроверитьРукопожатиеВебСокета();
Loading