Servidor Web: Requests e Roteamento

Escrito em 07 de setembro de 2019 por Lucas Vieira
lucasvieira@protonmail.com

Arquitetura de uma Aplicação Web

Uma aplicação web baseia-se em quatro camadas:

  • Client: Navegadores web, browsers móveis, aplicações que fazem requests via protocolo HTTP.
  • Server: Servidor web que intercepta requests feitos pelos clientes, e redireciona as respostas para os mesmos.
  • Business: Servidor de aplicação que faz o processamento requerido pelo servidor web, interagindo com a camada ou o banco de dados.
  • Data: Bancos de dados e outras fontes de dados.

Serviço web usando Node.js puro

Arquivo HTML para testes

index.html:

<!DOCTYPE html>
<html>
  <head>
    <meta charset='utf-8'>
    <title>Exemplo</title>
  </head>
  <body>
    <h1>Olá, mundo!</h1>
    <p>Esta é uma página de teste.</p>
  </body>
</html>

Servidor

Módulos requeridos

Podemos utilizar apenas módulos built-in para este exercício.

const http = require('http');
const fs   = require('fs');
const url  = require('url');

Handler do servidor

const httpHandler = (request, response) => {
    let pathname = url.parse(request.url).pathname;
    console.log("Requisição para " + pathname + " recebida.");

    fs.readFile(pathname.substr(1), (error, data) => {
        if(error) {
            // Se o arquivo não existe, retorne um código 404
            console.error(error);
            response.writeHead(404, { 'Content-Type': 'text/html' });
        } else {
            // Caso contrário, retorne o texto do arquivo,
            // com um código 200 (OK)
            response.writeHead(200, { 'Content-Type': 'text/html' });
            response.write(data.toString());
        }

        // Envie o corpo da resposta
        response.end();
    });
    
};

Binding do Handler com um servidor HTTP

O servidor ouvirá requisições na porta 8081 da máquina.

http.createServer(httpHandler)
    .listen(8081);

console.log("Servidor operando em http://127.0.0.1:8081/");

Para encerrar o servidor, use Ctrl+C.

Cliente

Opções de requerimento

Criamos um objeto contendo os dados requeridos.

const http = require('http');

let options = {
    host: 'localhost',
    port: '8081',
    path: '/index.html'
};

Callback para resposta

const handleResponse = (response) => {
    let body = '';
    
    response.on('data', data => {
        body += data;
    });

    response.on('end', () => {
        console.log(body);
    });
};

Fazendo a requisição

let req = http.request(options, handleResponse);
req.end();

Servidor web usando o framework Express

Criando o projeto

Criamos um diretório express_test/, onde iniciaremos um projeto Node.js.

# Caso já exista o diretório, apague
rm -rf express_test/

mkdir express_test/
cd express_test
npm init -y
npm install --save express

Exemplo: Hello World

const express = require('express');
const app     = express();

// Requisição roteada para a raiz do website (/)
app.get('/', (request, response) => {
    response.send('Hello, world!');
});

// Instanciando o server
let server = app.listen(8081, () => {
    let host = server.address().address;
    let port = server.address().port;

    console.log(`Servidor iniciado em http://${host}:${port}`);
});

Roteamento básico

const express = require('express');
const app     = express();

// GET Request para a homepage
app.get('/', (request, response) => {
    console.log("Requisição GET para a página inicial");
    response.send('Hello GET');
});

// POST Request para a homepage
app.post('/', (request, response) => {
    console.log("Requisição POST para a página inicial");
    response.send('Hello POST');
});

// DELETE Request para uma página
app.delete('/del_user', (request, response) => {
    console.log("Requisição DELETE para /del_user");
    response.send('Hello DELETE');
});

// GET Request para /abcd, /abxcd, /ab12345cd, etc.
// Veja o wildcard no ponto de entrada.
app.get('/ab*cd', (request, response) => {
    console.log("Requisição GET para /ab*cd");
    response.send('Hello GET');
});


let server = app.listen(8081, () => {
    let host = server.address().address;
    let port = server.address().port;

    console.log(`Servidor iniciado em http://${host}:${port}`);
});

Servindo arquivos estáticos

Criando diretório estático

Criamos o diretório public/, um subdiretório public/images/ e, dentro deste último, uma imagem PNG com ruído.

A geração da imagem necessita da ferramenta ImageMagick; qualquer outra imagem pode ser colocada no lugar.

mkdir -p express_test/public/images
convert -size 250x250 xc: +noise Random express_test/public/images/noise.png

Servindo os arquivos no diretório public/

const express = require('express');
const app     = express();

// Trata 'public' como a raiz do repositório,
// para arquivos estáticos e pontos de entrada
// que não foram previamente definidos
app.use(express.static('public'));

app.get('/', (request, response) => {
    console.log("Requisição GET para a página inicial");
    response.send('Hello GET');
});


let server = app.listen(8081, () => {
    let host = server.address().address;
    let port = server.address().port;

    console.log(`Servidor iniciado em http://${host}:${port}`);
});

Exercícios

De volta à página anterior