Entenda o middleware
O objetivo de um aplicativo web é receber e responder a solicitações HTTP. Uma solicitação é recebida e então o servidor gera a resposta apropriada. Tudo no ASP.NET Core está relacionado a esse ciclo de solicitação/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 recebe um objeto HttpContext e retorna um Task. O objeto HttpContext 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 umTask. O delegado escreve "Olá, mundo!" na resposta. - O segundo
app.Run()inicia o aplicativo.
Quando o aplicativo recebe uma solicitação HTTP, o delegado é chamado. O delegado escreve "Olá, mundo!" na resposta e conclui 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 considerado terminal ou não terminal. O middleware não terminal processa a solicitação e então 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.
Delegados adicionados com app.Use() podem ser middlewares terminais ou não terminais. Esses delegados esperam um objeto HttpContext e um objeto RequestDelegate 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 depois do próximo middleware. Um delegado adicionado com app.Use() tem duas oportunidades de agir em uma solicitação antes que a resposta seja enviada ao cliente; uma vez antes que a resposta seja gerada pelo middleware do terminal e novamente depois que a resposta é gerada pelo middleware do terminal.
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 esperam apenas um objeto HttpContext 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!" à resposta.
- Passa a solicitação para o próximo componente de middleware no pipeline e aguarda sua conclusão com
await next.Invoke(). - Após a conclusão do próximo componente no pipeline, 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.
Em tempo de execução, quando um navegador da web envia uma solicitação a esse aplicativo, os componentes de 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 interno
O ASP.NET Core fornece um conjunto de componentes de middleware integrados que você pode usar para adicionar funcionalidades comuns ao seu aplicativo. Além dos componentes de middleware adicionados explicitamente, alguns middlewares são adicionados implicitamente para você por padrão. Por exemplo, WebApplication.CreateBuilder() retorna um WebApplicationBuilder que adiciona o middleware de roteamento da 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 de 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 previne 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 de extremidade. O middleware de roteamento de ponto de extremidade é adicionado implicitamente peloWebApplicationBuilder.
Há muitos outros componentes de middleware integrados que você pode usar em seu aplicativo, dependendo do tipo de aplicativo e de suas necessidades. Consulte a documentação para a lista completa.
Dica
Nesse contexto, métodos que começam com Use são geralmente para mapeamento de middleware. Métodos que começam com Map geralmente são para mapear pontos de extremidade.
Importante
A ordem em que os componentes do middleware são adicionados ao pipeline é importante! Certos componentes de middleware devem ser executados antes de outros para funcionar corretamente. Verifique a documentação de cada componente de middleware para determinar a ordem correta.
