diff --git a/src/OneScript.Web.Server/WebServer.cs b/src/OneScript.Web.Server/WebServer.cs index 0dbe15af5..d06a876b9 100644 --- a/src/OneScript.Web.Server/WebServer.cs +++ b/src/OneScript.Web.Server/WebServer.cs @@ -14,10 +14,12 @@ This Source Code Form is subject to the terms of the using ScriptEngine.Machine.Contexts; using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Diagnostics; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; using OneScript.Execution; namespace OneScript.Web.Server @@ -36,6 +38,10 @@ public class WebServer: AutoContext private bool _useWebSockets = false; private (IRuntimeContextInstance Target, string MethodName)? _exceptionHandler = null; + /// + /// Порт прослушивателя. Если сервер создан с портом 0, свободный порт выбирает система, + /// и после запуска здесь будет выбранный порт + /// [ContextProperty("Порт", "Port", CanWrite = false)] public int Port { get; private set; } @@ -71,7 +77,18 @@ public void Run() { ConfigureApp(); - _app.Run(); + try + { + _app.Start(); + if (Port == 0) + Port = new Uri(_app.Urls.First()).Port; + + _app.WaitForShutdown(); + } + finally + { + _app.DisposeAsync().AsTask().Wait(); + } } /// diff --git a/tests/http.os b/tests/http.os index 9e6fb44ee..d5dbf9c10 100644 --- a/tests/http.os +++ b/tests/http.os @@ -1,7 +1,7 @@ Перем юТест; Перем мАдресРесурса; // URL ресурса (хоста) для тестирования запросов -Перем ПортТестовогоСервера; +Перем мВебсервер; // тестовый веб-сервер, запускается в фоновом задании Функция ПолучитьСписокТестов(ЮнитТестирование) Экспорт @@ -55,6 +55,14 @@ КонецЕсли; КонецПроцедуры +Процедура ПослеЗапускаТеста() Экспорт + // Тест мог упасть до конца, а сервер сам не остановится + Если мВебсервер <> Неопределено Тогда + мВебсервер.Остановить(); + мВебсервер = Неопределено; + КонецЕсли; +КонецПроцедуры + Процедура ТестДолжен_ПроверитьАвтоматическуюРаспаковкуGZip() Экспорт Запрос = Новый HttpЗапрос("/gzip"); @@ -467,12 +475,12 @@ МенеджерФоновыхЗаданий = Новый МенеджерФоновыхЗаданий; ЗаданиеВебсервера = МенеджерФоновыхЗаданий.Выполнить(ЭтотОбъект, "Вебсервер"); - ПортТестовогоСервера = 8181; - Соединение = Новый HTTPСоединение("http://127.0.0.1:" + ПортТестовогоСервера); + Соединение = Новый HTTPСоединение("http://127.0.0.1:" + ДождатьсяПортаСервера()); Запрос = Новый HTTPЗапрос("/"); - // Подождем пока поднимится сервер - Приостановить(1000); + // Первый запрос к только что запущенному серверу заметно медленнее следующих, + // поэтому время меряем на следующем + Соединение.ВызватьHTTPМетод("GET", Запрос).ПолучитьТелоКакСтроку(); Старт = ТекущаяУниверсальнаяДатаВМиллисекундах(); @@ -509,6 +517,22 @@ МенеджерФоновыхЗаданий.Очистить(); КонецПроцедуры +// Порт выбирает система, он становится известен после запуска сервера +Функция ДождатьсяПортаСервера() + + Попыток = 100; + Пока мВебсервер = Неопределено ИЛИ мВебсервер.Порт = 0 Цикл + Попыток = Попыток - 1; + Если Попыток = 0 Тогда + ВызватьИсключение "Тестовый веб-сервер не запустился"; + КонецЕсли; + Приостановить(100); + КонецЦикла; + + Возврат мВебсервер.Порт; + +КонецФункции + Функция ОбработчикЗапроса(Контекст, СледующийОбработчик) Экспорт Контекст.Ответ.КодСостояния = 200; @@ -529,9 +553,10 @@ Процедура Вебсервер() Экспорт - Вебсервер = Новый ВебСервер(ПортТестовогоСервера); - Вебсервер.ДобавитьОбработчикЗапросов(ЭтотОбъект, "ОбработчикЗапроса"); - Вебсервер.Запустить(); + // 0 - любой свободный порт, чтобы не мешать параллельным прогонам тестов + мВебсервер = Новый ВебСервер(0); + мВебсервер.ДобавитьОбработчикЗапросов(ЭтотОбъект, "ОбработчикЗапроса"); + мВебсервер.Запустить(); КонецПроцедуры