Программный вызов конвейера запросов ASP.NET Core
Вопрос
Есть ли способ программно вызывать конвейер запросов ASP.NET Core из моего собственного приложения, если у меня есть HTTP-глагол, маршрут, заголовки и полезная нагрузка тела?
Фон
В некоторых случаях WebAPI нашего приложения ASP.NET Core недоступен, так как приложение работает за брандмауэром или по другим причинам недоступно.
Чтобы обеспечить решение для этого сценария, мы хотим, чтобы наше приложение опрашивало некоторые другие службы на предмет "рабочих элементов", которые затем переводятся в вызовы API в нашем приложении.
Подходы, которые я рассмотрел
- Я мог бы просто попросить DI дать мне экземпляр контроллера и затем вызвать методы для него. Проблемы с этим подходом:
- Атрибуты авторизации не применяются. Но в нашем сценарии использования важно проверить токен на предъявителя. Поэтому здесь возникает вопрос: как программно вызвать промежуточное ПО авторизации?
- Я должен был бы направить входящие рабочие элементы на правильный контроллер / метод самостоятельно.
- С использованием
Microsoft.AspNetCore.TestHost
пакет, который я мог бы создатьTestClient
что позволяет мне делать запросы к себе (см. здесь). Но здесь есть пара неопределенностей:- Предполагаемый вариант использования этого
TestHost
для интеграционного тестирования. Безопасно ли использовать это в производственной среде? - Возможно ли вообще иметь такой
TestServer
работает рядом с обычным хостингом? - А как насчет поточной безопасности? Могу ли я создать несколько
TestClients
с одногоTestServer
например и использовать их из разных потоков?
- Предполагаемый вариант использования этого
Так что я уверен, что должен быть более чистый и прямой способ программно вызывать конвейер запросов из моего собственного приложения...
0 ответов
Да, на самом деле это довольно просто. Вы можете получить ссылку на конвейер запросов в конце метода Configure класса Startup. Сохраните его в статическом поле / одноэлементном сервисе / и т. Д.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// ... usual configuration code
AClass.PipelineStaticField = app.Build();
}
Затем в методе, который вы хотите ввести запрос, вам нужно создать HttpContext для передачи в конвейер.
var ctx = new DefaultHttpContext();
// setup a DI scope for scoped services in your controllers etc.
using var scope = _provider.CreateScope();
ctx.RequestServices = scope.ServiceProvider;
// prepare the request as needed
ctx.Request.Body = new MemoryStream(...);
ctx.Request.ContentType = "application/json";
ctx.Request.ContentLength = 1234;
ctx.Request.Method = "POST";
ctx.Request.Path = PathString.FromUriComponent("/mycontroller/action");
// you only need this if you are hosting in IIS (.UseIISIntegration())
ctx.Request.Headers["MS-ASPNETCORE-TOKEN"] = Environment.GetEnvironmentVariable("ASPNETCORE_TOKEN");
// setup a place to hold the response body
ctx.Response.Body = new MemoryStream();
// execute the request
await AClass.PipelineStaticField(ctx);
// interpret the result as needed, e.g. parse the body
ctx.Response.Body.Seek(0, SeekOrigin.Begin);
using var reader = new StreamReader(ctx.Response.Body);
string body = await reader.ReadToEndAsync();
Таким образом, ваш запрос будет проходить через весь конвейер, включая все промежуточное программное обеспечение, такое как аутентификация и авторизация.