Sisk

Manipuladores de servidor HTTP

Esta página foi traduzida automaticamente do inglês. Ler o original

Na versão 0.16 do Sisk, introduzimos a classe HttpServerHandler, que tem como objetivo estender o comportamento geral do Sisk e fornecer manipuladores de eventos adicionais ao Sisk, como tratamento de requisições Http, roteadores, sacos de contexto e mais.

A classe concentra eventos que ocorrem durante a vida útil de todo o servidor HTTP e também de uma requisição. O protocolo Http não possui sessões e, portanto, não é possível preservar informações de uma requisição para outra. O Sisk, por enquanto, fornece uma forma de você implementar sessões, contextos, conexões de banco de dados e outros provedores úteis para auxiliar seu trabalho.

Consulte esta página para ler onde cada evento é disparado e qual é seu propósito. Você também pode ver o ciclo de vida de uma requisição HTTP para entender o que acontece com uma requisição e onde os eventos são disparados. O servidor HTTP permite que você use múltiplos manipuladores ao mesmo tempo. Cada chamada de evento é síncrona, ou seja, bloqueará a thread atual para cada requisição ou contexto até que todos os manipuladores associados a essa função sejam executados e concluídos.

Ao contrário dos RequestHandlers, eles não podem ser aplicados a alguns grupos de rotas ou rotas específicas. Em vez disso, são aplicados a todo o servidor HTTP. Você pode aplicar condições dentro do seu Http Server Handler. Além disso, singletons de cada HttpServerHandler são definidos para cada aplicação Sisk, de modo que apenas uma instância por HttpServerHandler é criada.

Um exemplo prático de uso do HttpServerHandler é descartar automaticamente uma conexão de banco de dados ao final da requisição.

C#
// DatabaseConnectionHandler.cs

public class DatabaseConnectionHandler : HttpServerHandler
{
    protected override void OnHttpRequestClose(HttpServerExecutionResult result)
    {
        var requestBag = result.Request.Context.RequestBag;

        // verifica se a requisição definiu um DbContext
        // no seu ContextBag
        if (requestBag.IsSet<DbContext>())
        {
            var db = requestBag.Get<DbContext>();
            db.Dispose();
        }
    }
}

public static class DatabaseConnectionHandlerExtensions
{
    public static DbContext GetDbContext(this HttpRequest request)
    {
        return request.Bag.GetOrAdd(() => new DbContext());
    }
}

Com o código acima, a extensão GetDbContext permite que um contexto de conexão seja criado diretamente a partir do objeto HttpRequest. Uma conexão não descartada pode causar problemas ao operar com o banco de dados, portanto ela é encerrada em OnHttpRequestClose.

Você pode registrar um manipulador em um servidor Http no seu builder ou diretamente com HttpServer.RegisterHandler.

C#
// Program.cs

class Program
{
    static void Main(string[] args)
    {
        using var app = HttpServer.CreateBuilder()
            .UseHandler<DatabaseConnectionHandler>()
            .Build();

        app.Router.MapInstance(new UserController());
        app.Start();
    }
}

Com isso, a classe UsersController pode usar o contexto do banco de dados da seguinte forma:

C#
// UserController.cs

[RoutePrefix("/users")]
public class UserController : ApiController
{
    [RouteGet()]
    public async Task<HttpResponse> List(HttpRequest request)
    {
        var db = request.GetDbContext();
        var users = db.Users.ToArray();

        return JsonOk(users);
    }

    [RouteGet("<id>")]
    public async Task<HttpResponse> View(HttpRequest request)
    {
        var db = request.GetDbContext();

        int userId = request.RouteParameters["id"].GetInteger();
        var user = db.Users.FirstOrDefault(u => u.Id == userId);

        return JsonOk(user);
    }

    [RoutePost]
    public async Task<HttpResponse> Create(HttpRequest request)
    {
        var db = request.GetDbContext();
        var user = await request.GetJsonContentAsync<User>();

        ArgumentNullException.ThrowIfNull(user);

        db.Users.Add(user);
        await db.SaveChangesAsync();

        return JsonMessage("User added.");
    }
}

O código acima usa métodos como JsonOk e JsonMessage que são incorporados ao ApiController, que herda de um RouterController:

C#
// ApiController.cs

public class ApiController : RouterModule
{
    public HttpResponse JsonOk(object value)
    {
        return new HttpResponse(200)
            .WithContent(JsonContent.Create(value, null, new JsonSerializerOptions()
            {
                PropertyNameCaseInsensitive = true
            }));
    }

    public HttpResponse JsonMessage(string message, int statusCode = 200)
    {
        return new HttpResponse(statusCode)
            .WithContent(JsonContent.Create(new
            {
                Message = message
            }));
    }
}

Exceções lançadas pelos manipuladores #

Desde o Sisk 1.7, exceções lançadas pelos manipuladores do servidor são tratadas da seguinte forma:

  • Exceções lançadas em OnServerStarting, OnServerStarted e OnSetupRouter interrompem a inicialização do servidor. Elas são encapsuladas em um InvalidOperationException, com a exceção original em InnerException.
  • Exceções lançadas em outros eventos são gravadas em ErrorsLogsStream e os manipuladores restantes ainda são chamados, a menos que ThrowExceptions esteja habilitado. Com ThrowExceptions habilitado, elas são encapsuladas em um InvalidOperationException.
  • Exceções lançadas em OnHttpRequestClose e OnException, ou ao formatar os logs de acesso e erro, nunca escapam para o motor HTTP, mesmo com ThrowExceptions habilitado. Elas são gravadas em ErrorsLogsStream. Em versões anteriores, elas podiam terminar o processo ou deixar a conexão aberta.

Desenvolvedores podem implementar sessões, contextos e conexões de banco de dados usando esta classe. O código fornecido demonstra um exemplo prático com o DatabaseConnectionHandler, automatizando o descarte da conexão de banco de dados ao final de cada requisição.

A integração é simples, com manipuladores registrados durante a configuração do servidor. A classe HttpServerHandler oferece um conjunto de ferramentas poderoso para gerenciar recursos e estender o comportamento do Sisk em aplicações HTTP.

Digite para pesquisar na documentação e na referência da API.