Nancy – tratamento antes e depois do request (before and after hooks)

Facebooktwittergoogle_plusredditpinterestlinkedinmail

Já falamos do Nancy (um framework web extremamente leve para o .net) aqui anteriormente em mais de uma oportunidade (você pode conferir os outros posts clicando aqui). E hoje vamos ver como fazer tratamentos antes e depois de um request (requisição) recebido por nossa aplicação, o que pode ser útil por exemplo para gravar em um arquivo de log os parâmetros recebidos em todos os requests, ou até mesmo para fazer um cache de requests.

Vamos criar uma aplicação web com o template em branco e utilizando o framework 4.6.1 no Visual Studio, da mesma forma como fizemos nos demais posts sobre o Nancy aqui no blog, e após sua criação, vamos instalar o pacote do Nancy utilizando o Nuget:

Install-Package Nancy

Como host vamos utilizar o ASP.NET, então, instale também o pacote abaixo:

Install-Package Nancy.Hosting.Aspnet

Agora, vamos criar uma classe com o nome HelloNancy com o código abaixo:

using Nancy;
using Nancy.Extensions;

namespace NancyLog
{
    public class HelloNancy : NancyModule
    {
        public HelloNancy()
        {
            Get["/"] = p => "Hello Ninja";
            Get["/about"] = p => "This is a Nancy web app";
            Get["/hello/{nome}"] = p => $"Hello {p.nome}";
        }
    }
}

Com isso já temos nossa aplicação web rodando, mas não temos nenhuma novidade, então agora vamos ver como fazemos o tratamento para executar algum código antes e depois de cada request. Para começar, vamos ver como fazer um tratamento antes do request, que irá incrementar um contador que armazenará a quantidade de requests recebidos pela aplicação, então, adicione a linha abaixo para criar uma variável estática para o contador:

private static int qtd;

E agora adicione o código abaixo antes da linha que contém o nosso Get[“/”]:

Before += context => 
{
    qtd++;
    return null;
};

O Before é um pre-request hook, e é com ele que conseguimos fazer o tratamento que queremos antes da execução de qualquer outra rota definida. Veja que nós apenas incrementamos nossa variável, e retornamos null ao final, e esse é um ponto importante, se o Before retornar qualquer coisa diferente de null, esse retorno será devolvido como response para o request em questão, e nenhuma outra rota será chamada. Um recurso útil por exemplo se quisermos fazer alguma validação de segurança nesse momento, por exemplo, imagine que para acessar nossa aplicação seja obrigatório o envio de uma chave no cabeçalho da requisição, então nosso método Before poderia ficar assim:

Before += context =>
{
	if (!context.Request.Headers.Keys.Contains("nossa-chave"))
		return Response.AsText("Request Denied");
	else
		return null;
};

O que vai acontecer aqui, é que se o valor “nossa-chave” não for passado no cabeçalho, o Nancy já irá devolver como retorno o texto “Request Denied”, e nenhuma de nossas rotas será executada. Legal não?

Agora vamos ver como fazer o tratamento depois do request, e para isso nós vamos utilizar o método After, e o que iremos fazer, é alterar o response para acrescentar a quantidade total de requests que nossa aplicação recebeu. Para isso, coloque o código abaixo após o código do Before que fizemos logo acima:

After += context =>
{
    using (var memory = new MemoryStream())
    {
        context.Response.Contents.Invoke(memory);
        memory.Position = 0;
        using (var reader = new StreamReader(memory))
        {
            context.Response = $"{reader.ReadToEnd()} - Total de requests: {qtd}";
        }
    }
};

O que fizemos aqui, foi criar um MemoryStream para ler o conteúdo do response que foi gerado em uma de nossas rotas, e geramos um novo response concatenando o total de requests recebidos por nossa aplicação. Um ponto importante aqui, é que diferente do Before, onde um retorno era obrigatório, seja ele nulo ou com algum valor, aqui no After não é permitido nenhum tipo de retorno, caso contrário a aplicação não vai compilar.

Rode a aplicação e veja o resultado, você deve receber algo assim como retorno:

Hello Ninja - Total de requests: 1

E se trocarmos a chamada para a rota /about, receberemos algo assim:

This is a Nancy web app - Total de requests: 2

Agora vamos voltar à questão do pre-request, para ver como fazemos por exemplo para criarmos um log com os dados do request. Altere o código do Before para ficar da seguinte forma:

Before += context => 
{
    qtd++;
    System.Console.WriteLine($"URL: {context.Request.Url}");
    System.Console.WriteLine($"Conteúdo: {context.Request.Body.AsString()}");
    return null;
};

Nós temos acesso a todo o conteúdo do request, e podemos utilizá-lo para fazer validações como informado acima, ou então para criar log, que nesse nosso exemplo exibe no console a url completa e também o conteúdo do request.

O Nancy também permite fazer tratamento de erros, e vamos ver como em um futuro post, assim como outros recursos do Nancy, fique ligado.

O código completo de nossa aplicação ficou assim:

using Nancy;
using Nancy.Extensions;
using System.IO;

namespace NancyLog
{
    public class HelloNancy : NancyModule
    {
        private static int qtd;

        public HelloNancy()
        {
            Before += context => 
            {
                qtd++;
                System.Console.WriteLine($"URL: {context.Request.Url}");
                System.Console.WriteLine($"Conteúdo: {context.Request.Body.AsString()}");
                return null;
            };

            After += context =>
            {
                using (var memory = new MemoryStream())
                {
                    context.Response.Contents.Invoke(memory);
                    memory.Position = 0;
                    using (var reader = new StreamReader(memory))
                    {
                        context.Response = $"{reader.ReadToEnd()} - Total de requests: {qtd}";
                    }
                }
            };

            Get["/"] = p => "Hello Ninja";
            Get["/about"] = p => $"This is a Nancy web app";
            Get["/hello/{nome}"] = p => $"Hello {p.nome}";
        }
    }
}
Facebooktwittergoogle_plusredditpinterestlinkedinmail

1 thought on “Nancy – tratamento antes e depois do request (before and after hooks)

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *