Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 45 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@
* 2.3\. [Swagger UI](#swagger-ui)
* 3\. [Совместимость](#compatibility)
* 4\. [Программный интерфейс](#api)
* 5\. [Ограничения](#limitations)
* 6\. [Сравнение с httpbin.org](#comparison)
* 5\. [Кастомные эндпоинты](#custom-endpoints)
* 6\. [Ограничения](#limitations)
* 7\. [Сравнение с httpbin.org](#comparison)

## Установка <a name="installation"></a>

Expand All @@ -39,6 +40,7 @@ httpbin run
| --- | --- | --- |
| `-h`, `--host` | Имя хоста или IP-адрес сервиса | `127.0.0.1` |
| `-p`, `--port` | TCP-порт сервиса | `3333` |
| `--routes-handlers` | Путь к файлу или каталогу кастомных контроллеров | |

### Тестирование с [asserts](https://github.com/oscript-library/asserts) и [1connector](https://github.com/vbondarevsky/1connector) <a name="testing"></a>

Expand Down Expand Up @@ -132,6 +134,47 @@ IP-адрес или имя хоста.</br>
| `URL(<АдресРесурса>)` | Формирует полный URL-адрес сервиса с опциональным путем к ресурсу. |
| `ТаймаутЗапуска()` | Возвращает текущее значение таймаута запуска сервиса. |
| `УстановитьТаймаутЗапуска(<Таймаут>)` | Устанавливает максимальное время ожидания запуска сервиса. Применяется при синхронном запуске. |
| `РасположениеКонтроллеров()` | Возвращает текущий путь к папке или файлу с кастомными контроллерами. |
| `УстановитьРасположениеКонтроллеров(<Расположение>)` | Устанавливает путь к папке или файлу с кастомными контроллерами, определяющими маршруты сервиса. |

## Кастомные эндпоинты <a name="custom-endpoints"></a>

Сервис поддерживает подключение пользовательских контроллеров для расширения функциональности и добавления собственных эндпоинтов.

### Создание контроллера

Контроллер представляет собой класс OneScript с аннотацией `&Контроллер`, определяющей базовый путь маршрута. Более подробно можно прочитать в документации [WINOW](https://github.com/autumn-library/winow).

**Пример контроллера**

``` bsl
&Контроллер("/order")
Процедура ПриСозданииОбъекта()
КонецПроцедуры

&ТочкаМаршрута("add")
Процедура Главная(Ответ) Экспорт
// Бизнес-логика
КонецПроцедуры
```

### Подключение контроллеров

**Через программный интерфейс**

Для подключения кастомных контроллеров используйте метод `УстановитьРасположениеКонтроллеров()`, указав путь к папке или файлу с контроллерами:

``` bsl
HttpBin = Новый HttpBin()
.УстановитьРасположениеКонтроллеров("./path/to/routes")
.Запустить();
```

**Через CLI**

``` bash
httpbin run --routes-handlers './path/to/routes'
```

## Ограничения <a name="limitations"></a>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#Использовать "../internal"
#Использовать 1connector

Перем _Помощник; // ПомощникПодготовкиОтветов
Expand Down
5 changes: 4 additions & 1 deletion src/cmd/main.os
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
#Использовать autumn
#Использовать autumn-cli
#Использовать winow
#Использовать "."
#Использовать "../internal"

ПодключательКастомныхКонтроллеров = Новый ПодключательКастомныхКонтроллеров();
ПодключательКастомныхКонтроллеров.НайтиИПодключить();

Поделка = Новый Поделка;
Поделка.ЗапуститьПриложение();
36 changes: 22 additions & 14 deletions src/cmd/Классы/КомандаЗапустить.os
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// BSLLS:UsingHardcodeNetworkAddress-off

#Область Опции

&Опция(
Имя = "h host",
Описание = "Имя хоста или IP-адрес сервиса"
Expand All @@ -24,34 +26,40 @@
&ПоУмолчанию(0)
Перем _ИдентификаторРодительскогоПроцесса; // Число

&Пластилин("Настройки")
Перем _НастройкиВебСервера; // НастройкиВебСервера - см. winow
&Опция(
Имя = "routes-handlers",
Описание = "Путь к файлу или каталогу кастомных контроллеров"
)
&ТМассивСтрок
Перем _КастомныеКонтроллеры; // BSLLS:UnusedLocalVariable-off

#КонецОбласти

&Пластилин("ЗапускательВебПриложения")
Перем _ЗапускательВебПриложения; // ЗапускательВебПриложения - см. winow
#Область ОписаниеПеременных

&Пластилин("КонтроллерРодительскогоПроцесса")
Перем _КонтроллерРодительскогоПроцесса; // КонтроллерРодительскогоПроцесса

&Пластилин("ЗапускательСервиса")
Перем _ЗапускательСервиса; // ЗапускательСервиса

#КонецОбласти

#Область СлужебныеПроцедурыИФункции

&КомандаПриложения(Имя = "run", Описание = "Запуск сервиса")
Процедура ПриСозданииОбъекта()
КонецПроцедуры

&ВыполнениеКоманды
Процедура Запустить() Экспорт

_НастройкиВебСервера.РазмерБуфера = 0;
_НастройкиВебСервера.ИмяХоста = _Хост;
_НастройкиВебСервера.Порт = _Порт;

Если ПолучитьПеременнуюСреды("HTTPBIN_IS_TEST_MODE") = "true" Тогда
_НастройкиВебСервера.ЗадержкаПередЧтениемСокета = 400;
КонецЕсли;

Если _ИдентификаторРодительскогоПроцесса > 0 Тогда
_КонтроллерРодительскогоПроцесса.НачатьНаблюдение(_ИдентификаторРодительскогоПроцесса);
КонецЕсли;

_ЗапускательВебПриложения.Запустить();
_ЗапускательСервиса.Запустить(_Хост, _Порт);

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

КонецПроцедуры
#КонецОбласти
41 changes: 35 additions & 6 deletions src/core/Классы/HttpBin.os
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@
#Использовать fs
#Использовать logos

Перем _ТаймаутЗапуска; // Число - Таймаут запуска сервиса в секундах
Перем _ТаймаутПроверки; // Число - Таймаут HTTP-проверки доступности в секундах
Перем _ИмяХоста; // Строка - IP-адрес или доменное имя хоста
Перем _Порт; // Число - Номер TCP-порта сервиса
Перем _Процесс; // Процесс, Неопределено - Объект запущенного процесса
Перем _Лог; // Лог - Логгер для отладочной информации
Перем _ТаймаутЗапуска; // Число - Таймаут запуска сервиса в секундах
Перем _ТаймаутПроверки; // Число - Таймаут HTTP-проверки доступности в секундах
Перем _ИмяХоста; // Строка - IP-адрес или доменное имя хоста
Перем _Порт; // Число - Номер TCP-порта сервиса
Перем _РасположениеКонтроллеров; // Строка, Неопределено - Путь к папке или файлу с кастомными контроллерами
Перем _Процесс; // Процесс, Неопределено - Объект запущенного процесса
Перем _Лог; // Лог - Логгер для отладочной информации

#Область ПрограммныйИнтерфейс

Expand Down Expand Up @@ -197,6 +198,28 @@
Возврат _ТаймаутЗапуска;
КонецФункции

// Устанавливает путь к папке или файлу с кастомными контроллерами, определяющими маршруты сервиса.
//
// Параметры:
// Расположение - Строка - Путь к папке или файлу с контроллерами (например, "./controllers" или "./МойКонтроллер.os")
//
// Возвращаемое значение:
// ЭтотОбъект - Для возможности цепочки вызовов
//
Функция УстановитьРасположениеКонтроллеров(Расположение) Экспорт
_РасположениеКонтроллеров = Расположение;
Возврат ЭтотОбъект;
КонецФункции

// Возвращает текущий путь к папке или файлу с кастомными контроллерами.
//
// Возвращаемое значение:
// Строка, Неопределено
//
Функция РасположениеКонтроллеров() Экспорт
Возврат _РасположениеКонтроллеров;
КонецФункции

#КонецОбласти

#Область СлужебныеПроцедурыИФункции
Expand Down Expand Up @@ -242,6 +265,12 @@
СтрокаКоманды.Добавить(Формат(_Порт, "ЧГ="));
СтрокаКоманды.Добавить("--parent-pid");
СтрокаКоманды.Добавить(Формат(ТекущийПроцесс().Идентификатор, "ЧГ="));

Если ЗначениеЗаполнено(_РасположениеКонтроллеров) Тогда
СтрокаКоманды.Добавить("--routes-handlers");
СтрокаКоманды.Добавить(ОбернутьВКавычки(_РасположениеКонтроллеров));
КонецЕсли;

СтрокаКоманды = СтрСоединить(СтрокаКоманды, " ");

_Лог.Отладка("Запуск процесса: %1", СтрокаКоманды);
Expand Down
43 changes: 43 additions & 0 deletions src/internal/Классы/ЗапускательСервиса.os
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@

#Использовать winow

Перем _Хост; // Строка
Перем _Порт; // Число

&Пластилин("Настройки")
Перем _НастройкиВебСервера; // Настройки - см. winow

&Пластилин("ЗапускательВебПриложения")
Перем _ЗапускательВебПриложения; // ЗапускательВебПриложения - см. winow

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

// Запускает сервис через winow
//
// Параметры:
// Хост - Строка - IP-адрес или имя хоста
// Порт - Число - Номер TCP-порта
Процедура Запустить(Хост, Порт) Экспорт

_Хост = Хост;
_Порт = Порт;

НастроитьВебСервер();

_ЗапускательВебПриложения.Запустить();

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

Процедура НастроитьВебСервер()

_НастройкиВебСервера.РазмерБуфера = 0;
_НастройкиВебСервера.ИмяХоста = _Хост;
_НастройкиВебСервера.Порт = _Порт;

Если ПолучитьПеременнуюСреды("HTTPBIN_IS_TEST_MODE") = "true" Тогда
_НастройкиВебСервера.ЗадержкаПередЧтениемСокета = 400;
КонецЕсли;

КонецПроцедуры
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#Использовать fs

#Область ПрограммныйИнтерфейс

// Находит и подключает кастомные контроллеры из путей, указанных в аргументах командной строки.
//
Процедура НайтиИПодключить() Экспорт

МассивФайлов = НайтиФайлыИзПереданныхАргументов();

Для Каждого ПолноеИмя Из МассивФайлов Цикл

Если ФС.КаталогСуществует(ПолноеИмя) Тогда
ПодключитьИзКаталога(ПолноеИмя);
ИначеЕсли ФС.ФайлСуществует(ПолноеИмя) Тогда
Подключить(ПолноеИмя);
Иначе
ВызватьИсключение СтрШаблон("Не удалось подключить контроллер '%1': файл не существует", ПолноеИмя);
КонецЕсли;

КонецЦикла;

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

// Подключает контроллер из указанного файла.
//
// Параметры:
// ПолноеИмя - Строка - Полный путь к файлу контроллера (.os)
//
Процедура Подключить(ПолноеИмя) Экспорт

Имя = Новый Файл(ПолноеИмя).ИмяБезРасширения;

Попытка
ПодключитьСценарий(ПолноеИмя, Имя);
Исключение
ВызватьИсключение СтрШаблон(
"Не удалось подключить контроллер '%1': %2",
ПолноеИмя,
КраткоеПредставлениеОшибки(ИнформацияОбОшибке())
);
КонецПопытки;

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

#КонецОбласти

#Область СлужебныеПроцедурыИФункции

Процедура ПодключитьИзКаталога(Каталог)

Файлы = НайтиФайлы(Каталог, "*.os");

Для Каждого Файл Из Файлы Цикл
Подключить(Файл.ПолноеИмя);
КонецЦикла;

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

Функция НайтиФайлыИзПереданныхАргументов()

Файлы = Новый Массив();

НайденКлюч = Ложь;
Для Каждого Значение Из АргументыКоманднойСтроки Цикл

Если НайденКлюч Тогда
Файлы.Добавить(Значение);
НайденКлюч = Ложь;
Продолжить;
КонецЕсли;

Если Значение = "--routes-handlers" Тогда
НайденКлюч = Истина;
КонецЕсли;

КонецЦикла;

Возврат Файлы;

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

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Fix argument parsing to collect all values after the flag.

The current implementation only collects ONE value immediately after each --routes-handlers flag occurrence. If a user passes multiple paths like --routes-handlers file1.os file2.os, only file1.os will be collected and file2.os will be silently dropped.

This silent data loss can lead to confusion and missing controller registrations.

Apply this diff to collect all values after the flag until the next flag is encountered:

 Функция НайтиФайлыИзПереданныхАргументов()

 	Файлы = Новый Массив();

 	НайденКлюч = Ложь;
 	Для Каждого Значение Из АргументыКоманднойСтроки Цикл

+		Если СтрНачинаетсяС(Значение, "--") Тогда
+			Если Значение = "--routes-handlers" Тогда
+				НайденКлюч = Истина;
+			Иначе
+				НайденКлюч = Ложь;
+			КонецЕсли;
+			Продолжить;
+		КонецЕсли;
+
 		Если НайденКлюч Тогда
 			Файлы.Добавить(Значение);
-			НайденКлюч = Ложь;
-			Продолжить;
 		КонецЕсли;

-		Если Значение = "--routes-handlers" Тогда
-			НайденКлюч = Истина;
-		КонецЕсли;
-
 	КонецЦикла;

 	Возврат Файлы;

 КонецФункции

This change allows collecting multiple paths: --routes-handlers file1.os file2.os file3.os while still supporting repeated flags: --routes-handlers file1.os --routes-handlers file2.os.

🤖 Prompt for AI Agents
In src/internal/Классы/ПодключательКастомныхКонтроллеров.os around lines 60-81,
the current loop sets НайденКлюч true only to add a single following value then
clears it, so subsequent values after the flag are ignored; change the parsing
so that when "--routes-handlers" is seen you set НайденКлюч = Истина and then
for each following argument, if НайденКлюч and the argument does NOT start with
"-" (i.e., is not another flag) add it to Файлы and keep НайденКлюч true; if the
argument starts with "-" treat it as a new flag by setting НайденКлюч = Ложь and
re-evaluating that argument as a flag (do not consume it as a value). This
collects multiple paths after one flag and still supports repeated flags.


#КонецОбласти
Loading