Aplicativos web em C++ usando o Tufão

Quando eu comento sobre desenvolvimento web em C++ a alguns programadores, eles demonstram uma falta de fé perceptível na ideia, enquanto outros ficam curiosos e começam a discutir como as peculiaridades da linguagem afetam o seu uso na área. Inspirado pela framework Node.js, desenvolvi o Tufão.

[ Hits: 23.719 ]

Por: Vinícius dos Santos Oliveira em 12/06/2012 | Blog: https://vinipsmaker.github.io/


Arquitetura do Tufão



O Tufão é inspirado no projeto Node.js. Assim, o núcleo de ambos é bem similar. Para suprir a programação orientada a eventos do JavaScript usada no Node.js, o mecanismo Signals & Slots do Qt é utilizado.

Com exceção dos DEFINEs (por motivos óbvios), todos os símbolos declarados nos cabeçalhos da biblioteca pertencem ao namespace Tufao e todos os arquivos de cabeçalho encontram-se dentro da pasta Tufao.

O principal trabalho de uma biblioteca que abstrai o protocolo HTTP é interpretar e formatar mensagens. No Tufão, esse trabalho é feito pelas classes HttpServerRequest e HttpServerResponse, respectivamente. Para facilitar ainda mais o processo, existem as classes HttpServer e HttpsServer, que abstraem o processo de tratar conexões TCP e SSL. Em uma aplicação Hello World, você chamaria a função QObject::connect para realizar a parte principal do trabalho:

QObject::connect(&server,
                 SIGNAL(requestReady(Tufao::HttpServerRequest*,Tufao::HttpServerResponse*)),
                 &handler,
                 SLOT(handleRequest(Tufao::HttpServerRequest*,Tufao::HttpServerResponse*)));

E implementaria o handler com o seguinte SLOT:

void Handler::handleRequest(Tufao::HttpServerRequest *request,
                            Tufao::HttpServerResponse *response)
{
    response->writeHead(Tufao::HttpServerResponse::OK);
    response->headers().insert("Content-Type", "text/plain");
    response->end("Hello World\n");
}

Os principais métodos da classe HttpServerResponse são writeHead, headers, write e end. Com eles, é possível formar e enviar a mensagem de resposta para a requisição. Como visto anteriormente, a mensagem possui partes bem definidas e ordenadas, não sendo possível enviar o corpo de mensagem antes dos cabeçalhos, por exemplo. Assim, você deve chamar os métodos em ordem.

A primeira informação que você deve fornecer é a linha de status, que informa um código indicando a validade da requisição, através do método writeHead. Após isso você pode enviar quantos pedaços da mensagem quiser, através do método write, e finalizar a resposta com o método end.

Duas características importantes a ter em mente é que qualquer cabeçalho a ser definido, deve sê-lo antes de qualquer chamada a write, e que a versão 1.0 do protocolo HTTP não suporta receber a mensagem em pedaços. Assim, nesses casos, o Tufão irá usar um buffer interno para guardar todos os pedaços na memória antes de enviá-los. Dependendo de sua aplicação, pode ser interessante bloquear certas páginas para clientes que usam o HTTP/1.0, ou mesmo enviar uma entidade alternativa.

No Tufão 1.0 (que pretendo lançar após o Qt5), pretendo permitir o uso lambdas em vários pontos onde fazem sentido, mas, no momento, isso não é possível de modo natural. Essa funcionalidade permitirá criar aplicações usando ainda menos linhas de código e, ao mesmo tempo, torná-las mais legíveis.

Um dos problemas em tratar requisições HTTP da forma demonstrada no código anterior é a possibilidade de criar "classes Megazord". Caso você não tenha imaginado como isso pode ocorrer, o seguinte pedaço de código pode lhe dar uma pista:

if (request->url() == "/user") {
    // ...
} else if (request->url() == "/community") {
    // ...
} else if (request->url() == "/page") {
    // ...
} else if (request->url() == "/about") {
    // ...

Para evitar o tratamento de várias páginas diferentes na mesma função, você pode usar um roteador de requisições, que encaminha as requisições para os handlers corretos. O roteador disponível no Tufão permite que você utilize expressões regulares para filtrar a URL das requisições e filhos da classe AbstractHttpServerRequestHandler como handlers.

Os handlers implementam o método handleRequest, que retorna um valor booleano indicando se a requisição foi ou não tratada. Caso a requisição não seja tratada, ela é encaminhada para o próximo handler cujo filtro satisfaz a requisição. Essa arquitetura é bem flexível e útil. Dois usos interessantes são criar handlers do tipo fallback (para navegadores antigos, por exemplo) e criar handlers que definem cabeçalhos que devem estar presentes em todas as respostas (o cabeçalho Date, por exemplo).

Duas particularidades presentes no roteamento de requisições do Tufão é que é possível aninhar roteadores, pois a classe que faz o roteamento também é filha de AbstractHttpServerRequestHandler, e é possível carregar plugins para usar como handlers, através da classe HttpPluginServer. Para ter uma ideia rápida de como utilizar esses recursos do Tufão, crie, no QtCreator, uma aplicação a partir do modelo "application":
E leia a documentação caso queira detalhes de como os mesmos se comportam. Existem várias outras facilidades documentadas disponíveis no Tufão, leiam a documentação.

Página anterior     Próxima página

Páginas do artigo
   1. Introdução
   2. Um pouco sobre HTTP
   3. Arquitetura do Tufão
   4. WebSocket
   5. Criando uma aplicação de chat
Outros artigos deste autor

Próximas Tecnologias do Sistema GNU/Linux

GNU Emacs, o primeiro GNU

Entendendo os codecs, os containers formats e por que o Ogg é tão bom

VLC Media Player (parte 2)

VLC Media Player

Leitura recomendada

Biblioteca VBMcgi: Crie aplicações Web CGI em C++ com acesso ao banco Interbase/Firebird sem mistério

Criando aplicações RESTful com Qt e Cutelyst

DotGNU: a resposta Open Source ao dotNET

Cuidado com números em Ponto Flutuante

Aprendendo a utilizar o GNU Debugger (parte 1)

  
Comentários
[1] Comentário enviado por bolche em 12/06/2012 - 14:23h

Legal, tava querendo brincar de aplicativos web em C++ faz um tempo.
Você podia aproveitar a infraestrutura de outro servidor web ao invés de fazer tudo do zero, por exemplo o apache, modificar o processo de construção para construir um módulo do apache ao invés de um servidor standalone. Talvez um protocolo mais agnóstico como FastCGI seja ainda melhor.
De qualquer maneira, muito legal!

[2] Comentário enviado por vinipsmaker em 12/06/2012 - 15:59h


[1] Comentário enviado por bolche em 12/06/2012 - 14:23h:

Legal, tava querendo brincar de aplicativos web em C++ faz um tempo.
Você podia aproveitar a infraestrutura de outro servidor web ao invés de fazer tudo do zero, por exemplo o apache, modificar o processo de construção para construir um módulo do apache ao invés de um servidor standalone. Talvez um protocolo mais agnóstico como FastCGI seja ainda melhor.
De qualquer maneira, muito legal!


Não criei tudo do 0, utilizo o parser HTTP criado durante o projeto Node.js.

E já pensei sobre o uso de FastCGI, mas queria diminuir o gargalo para aumentar o desempenho e fazer um servidor standalone é uma das estratégias. Isso, só ressaltando, traz outras implicações, mas é fácil contornar essa decisão usando, no Apache mesmo, proxy reverso ( http://httpd.apache.org/docs/2.0/mod/mod_proxy.html ).

[3] Comentário enviado por julio_hoffimann em 12/06/2012 - 19:45h

Parabéns pelo projeto Vinícius!

Abraço!

[4] Comentário enviado por fabio em 12/06/2012 - 20:00h

Muito bom mesmo. Como é o desempenho de sites em C++ se comparados com linguagens interpretadas, tal como o PHP? Vale a pena?

[5] Comentário enviado por julio_hoffimann em 12/06/2012 - 20:13h

Estava tentando lembrar o nome de um projeto recente da Google para aplicações web em código nativo: http://www.youtube.com/watch?v=UUnC5y4j0As

A idéia é poder rodar aplicações C/C++ ou outras linguagem de alta performance no navegador de forma segura, talvez seja de interesse do autor. ;-)

Abraço!

[6] Comentário enviado por vinipsmaker em 12/06/2012 - 22:24h


[5] Comentário enviado por julio_hoffimann em 12/06/2012 - 20:13h:

Estava tentando lembrar o nome de um projeto recente da Google para aplicações web em código nativo: http://www.youtube.com/watch?v=UUnC5y4j0As

A idéia é poder rodar aplicações C/C++ ou outras linguagem de alta performance no navegador de forma segura, talvez seja de interesse do autor. ;-)

Abraço!


http://en.wikipedia.org/wiki/Google_Native_Client ? Já conhecia.
:P

[7] Comentário enviado por vinipsmaker em 13/06/2012 - 09:09h


[4] Comentário enviado por fabio em 12/06/2012 - 20:00h:

Muito bom mesmo. Como é o desempenho de sites em C++ se comparados com linguagens interpretadas, tal como o PHP? Vale a pena?


Tem um texto onde eu discuti bastante sobre a escolha da linguagem para o Tufão:
http://vinipsmaker.wordpress.com/2012/05/07/understanding-tufao-part-1/

Mas, para discutir sobre desempenho, eu preciso fazer benchmarks, para não caminhar muito na direção do "achismo". Fico devendo um benchmark.


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner
Linux banner
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts