Compreender o middleware
O objetivo de um aplicativo Web é receber e responder a solicitações HTTP. Uma solicitação é recebida e, em seguida, o servidor gera a resposta apropriada. Tudo no ASP.NET Core está relacionado com este ciclo de pedido/resposta.
Quando um aplicativo ASP.NET Core recebe uma solicitação HTTP, ele passa por uma série de componentes para gerar a resposta. Esses componentes são chamados de middleware. O middleware pode ser pensado como um pipeline pelo qual a solicitação flui, e cada camada de middleware pode executar código antes e depois da próxima camada no pipeline.
Middleware e delegados
O middleware é implementado como um delegado que pega um HttpContext objeto e retorna um Taskarquivo . O HttpContext objeto representa a solicitação e a resposta atuais. O delegado é uma função que processa a solicitação e a resposta.
Por exemplo, considere o seguinte código:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Run(async context =>
{
await context.Response.WriteAsync("Hello world!");
});
app.Run();
No código anterior:
-
WebApplication.CreateBuilder(args)cria um novoWebApplicationBuilderobjeto. -
builder.Build()cria um novoWebApplicationobjeto. - O primeiro
app.Run()define um delegado que pega umHttpContextobjeto e retorna umTaskarquivo . O delegado escreve "Olá mundo!" para a resposta. - O segundo
app.Run()inicia o aplicativo.
Quando o aplicativo recebe uma solicitação HTTP, o delegado é chamado. O delegado escreve "Olá mundo!" para a resposta e completa a solicitação.
Encadeamento de middleware
Na maioria dos aplicativos, você tem vários componentes de middleware que são executados em sequência. A ordem em que você adiciona componentes de middleware ao pipeline é importante. Os componentes são executados na ordem em que foram adicionados.
Middleware terminal e não terminal
Cada middleware pode ser pensado como terminal ou não. O middleware não terminal processa a solicitação e, em seguida, chama o próximo middleware no pipeline. O middleware de terminal é o último middleware no pipeline e não tem um próximo middleware para chamar.
Os delegados adicionados com app.Use() podem ser middleware terminal ou não terminal. Esses delegados esperam um HttpContext objeto e um RequestDelegate objeto como parâmetros. Normalmente, o delegado inclui await next.Invoke();. Isso passa o controle para o próximo middleware no pipeline. O código antes dessa linha é executado antes do próximo middleware e o código depois dessa linha é executado após o próximo middleware. Um delegado adicionado com app.Use() obtém duas oportunidades de agir em uma solicitação antes que a resposta seja enviada ao cliente: uma vez antes da resposta ser gerada pelo middleware do terminal e novamente depois que a resposta for gerada pelo middleware do terminal.
Os delegados adicionados com app.Run() são sempre middleware de terminal. Eles não chamam o próximo middleware no pipeline. Eles são o último componente de middleware que é executado. Eles só esperam um HttpContext objeto como parâmetro.
app.Run() é um atalho para adicionar middleware de terminal.
Considere o seguinte exemplo:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Use(async (context, next) =>
{
await context.Response.WriteAsync("Hello from middleware 1. Passing to the next middleware!\r\n");
// Call the next middleware in the pipeline
await next.Invoke();
await context.Response.WriteAsync("Hello from middleware 1 again!\r\n");
});
app.Run(async context =>
{
await context.Response.WriteAsync("Hello from middleware 2!\r\n");
});
app.Run();
No código anterior:
-
app.Use()Define um componente de middleware que:- Escreve "Olá do middleware 1. Passando para o próximo middleware!" para a resposta.
- Passa a solicitação para o próximo componente de middleware no pipeline e aguarda que ele seja concluído com
await next.Invoke(). - Depois que o próximo componente no pipeline for concluído, ele escreve "Olá do middleware 1 novamente!"
- O primeiro
app.Run()define um componente de middleware que escreve "Olá do middleware 2!" na resposta. - O segundo
app.Run()inicia o aplicativo.
No tempo de execução, quando um navegador da Web envia uma solicitação para esse aplicativo, os componentes do middleware são executados na ordem em que foram adicionados ao pipeline. O aplicativo retorna a seguinte resposta:
Hello from middleware 1. Passing to the next middleware!
Hello from middleware 2!
Hello from middleware 1 again!
Middleware integrado
O ASP.NET Core fornece um conjunto de componentes de middleware internos que você pode usar para adicionar funcionalidade comum ao seu aplicativo. Além dos componentes de middleware explicitamente adicionados, alguns middleware são implicitamente adicionados para você por padrão. Por exemplo, WebApplication.CreateBuilder() retorna um WebApplicationBuilder que adiciona o middleware de roteamento de página de exceção do desenvolvedor, adiciona condicionalmente o middleware de autenticação e autorização se os serviços relacionados estiverem configurados e adiciona o middleware de roteamento de ponto de extremidade.
Por exemplo, considere o seguinte arquivo Program.cs :
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error", createScopeForErrors: true);
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseAntiforgery();
app.MapStaticAssets();
app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode();
app.Run();
No código anterior:
-
app.UseExceptionHandler()Adiciona um componente de middleware que captura exceções e retorna uma página de erro. -
app.UseHsts()adiciona um componente de middleware que define o cabeçalho Strict-Transport-Security. -
app.UseHttpsRedirection()adiciona um componente de middleware que redireciona solicitações HTTP para HTTPS. -
app.UseAntiforgery()adiciona um componente de middleware que impede ataques de falsificação de solicitação entre sites (CSRF). -
app.MapStaticAssets()eapp.MapRazorComponents<App>()mapear rotas para pontos de extremidade, que são então manipulados pelo middleware de roteamento de ponto final. O middleware de roteamento de ponto de extremidade é adicionado implicitamente peloWebApplicationBuilder.
Há muito mais componentes de middleware internos que você pode usar em seu aplicativo, dependendo do tipo de aplicativo e de suas necessidades. Consulte a documentação para obter a lista completa.
Gorjeta
Nesse contexto, os métodos que começam com Use geralmente são para mapeamento de middleware. Os métodos que começam com Map geralmente são para mapear pontos de extremidade.
Importante
Os componentes do middleware do pedido são adicionados ao pipeline importa! Certos componentes de middleware devem ser executados antes de outros para funcionarem corretamente. Verifique a documentação de cada componente de middleware para determinar a ordem correta.