Esse guia-artigo é o primeiro de uma série de artigos referentes a Node e tem o intuito de ensinar as primeiras noções de web server com node, primeiro instalando o ambiente e fazendo um 'Hello, World'.

Aqui você vai aprender a:

  • Instalar e utilizar uma ação do httpie, um cliente http;
  • Instalar e utilizar uma ação do ngrok, um software de proxy reverso;
  • Instalar nvm, um gerenciador de versões do node;
  • Instalar e utilizar node como web server, sem pacotes externos. Na pegada pureza total.

Vamos assumir que você vai utilizar um sistema com Ubuntu, em particular, o release 16.04.1 instalado e já tenha um editor de texto da sua escolha. Com exceção do Windows, as instalações feitas em sistemas nix não devem alterar muito, apesar de usar gerenciadores de pacotes diferentes. Vamos assumir também que você acabou de instalar este sistema mas sabe como abrir terminal e como linha de comando funciona.

A ideia é que este guia seja usado como referência para os próximos tutoriais que utilizaremos, como 'Aloô, skynet! O seu primeiro bot no messenger', e nosso tutorial de um 'Hello, world!' em um chatbot.

Nota:
Você vai encontrar nos textos seguidos por mim duas marcações, tldr e eli5, a primeira (too long; didn't read) é se você não está interessado em ler tudo, essa marcação vai apontar para uma sessão do texto que vai conter a informação mais importante ou resumida do que o artigo trata.
No reddit existe uma comunidade lá chamada eli5 que significa Me explique como se eu tivesse 5 anos, que é uma forma de pedir para alguém explicar em termos mais simples uma certa situação que é cheia de termos técnicos ou possui uma complexidade um pouco elevada.


Vamos lá!

Esse guia vai passar pelas seguintes etapas:

  1. Instalação de ngrok;
  2. Instalação do httpie;
  3. Instalação do nvm;
  4. Instalação do node;
  5. Criação de um web server com node.
  6. Testando nosso web server.

tldr: Se você é apressado, ou já tem tudo instalado e só quer o código, ctrl + f em #5 Criação para ir direto ao código.

#1. Instalação do ngrok

ngrok, em termos técnicos, funciona como proxy reverso criando um tunnel entre sua rede e a rede do ngrok, expondo um acesso virtual para receber pedidos http, o que é útil quando sua rede está atrás de um firewall ou não tem portas abertas. Além disso, ele fornece um endereço https para que você receba requisições, o que é uma putz praticidade pra quem quer apenas fazer experimentações rápidas e fazer uso de algumas APIs como a do próprio messenger.

Existe duas maneiras de instalá-lo: a primeira é pelo apt-get e a última é pelo próprio site do ngrok citado acima. Vamos usar a segunda, porque queremos a versão mais atual e a versão disponibilizada pelo apt repository é 1.6 que não possui mais suporte da equipe de dev. Por tanto, entre no site e faça o download de lá. Não precisa de instalação, basta você ir no seu terminal, e rodá-lo.
Por exemplo, meu ngrok foi baixado em ~/Downloads, então o comando para rodar seria ~/Downloads/ngrok. No entanto, ngrok precisa de mais informações para executar a função para que ele feito e por isso precisamos passar a porta que queremos utilizar e o protocolo que queremos utilizar, a execução ficará assim:

~/Downloads/ngrok http 8080

Após execução, ngrok vai gerar duas urls, uma http e outra https:

Forwarding   http://38504fd3.ngrok.io -> localhost:8080
Forwarding   https://38504fd3.ngrok.io -> localhost:8080

E prontinho, sua máquina está exposta para receber chamadas http por um endereço https.

#2. Instalação do httpie

A segunda ferramenta que vamos utilizar é o httpie. Na mesma onda, em termos técnicos, ele é um cliente http de terminal. Nós vamos usá-lo para enviar requisições http para o endereço que expomos utilizando ngrok e verificar se estamos fazendo nossa api adequadamente.
Para instalação, podemos utilizar o apt-get, então basta no terminal digitar:

sudo apt-get install httpie 

Para verificar se ele foi instalado, basta digitar

http --version

E finalmente para utilização, basta verificar digitando http. Para o nosso caso vamos fazer bem simples, um exemplo seria:

http GET https://38504fd3.ngrok.io/hello

Essa URL vai ser a gerada pelo ngrok, então ela vai ser uma particular ao seu caso.

#3. Instalação do nvm

É interessante usar um gerenciador de versões porque dá liberdade para utilizar versões diferentes de node sem dor de cabeça, em particular o nvm, a instalação dele é bem simples, basta você digitar isso no terminal:

curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.8/install.sh | bash

Caso reclame do curl,

sudo apt-get install curl

A instalação do nvm, você pode verificar por:

nvm --version

#4. Instalação do node

Agora precisamos instalar uma versão do node de fato.
Fazemos isso com:

nvm install --lts

O nvm então vai instalar a versão que possui estado de LTS (Long Term Support) que de maneira simples, significa ter uma versão estável e com suporte por um bom período de tempo.

Após instalação, você pode verificar sua versão do node com

node --version

#5. Criação de um web server com node

E agora precisamos criar nosso server.
A documentação no site do node sobre isso é bem simples, porém extensa para apenas o que a gente precisa nesse momento. Basicamente, precisamos de algo que permita uma criar uma aplicação de web server ao ser executado.
Quem libera isso é um método do pacote http, o http.createServer (não confunda com o http do httpie) no node. Para ter acesso a ele é necessário importar o pacote http.

Em seu editor de texto favorito, crie um arquivo main.js e adicione o seguinte conteúdo:

const http = require('http');
const port = 8080;

http.createServer((request, response) => {
    if (request.url === '/hello') {
        if (request.method === 'GET') {
            console.log('Hello, getty!');
            response.end();
        } else if (request.method === 'POST') {
            console.log('Heello, posty!');
            response.end();
        }
    }
}).listen(port, function() {
    console.log(`Rodando na porta ${port}`);
});

O trecho do http.createServer é uma forma compacta de escrever o seguinte:

const http = require('http');
const port = 8080;
const server = http.createServer();

server.on('request', (request, response) => {
    if (request.url === '/hello') {
        if (request.method === 'GET') {
            console.log('Hello, getty!');
            response.end();
        } else if (request.method === 'POST') {
            console.log('Heello, posty!');
            response.end();
        }
    }
});
server.listen(port, function() {
    console.log(`Rodando na porta ${port}`);
});

Vamos por partes explicando o que cada parte significa:

const http = require('http');

Funcionalidades no node são separadas por modules (módulos), como dissemos precisamos do método createServer que está no módulo http. Aqui estamos definindo que queremos utilizar o pacote http do node.

const port = 8080;

Definimos uma porta desejada para ser utilizada.

const server = http.createServer();

http.createServer é o método responsável por criar nosso objeto web server, um Server object, ele é o que chamamos de EventEmitter, um emissor de eventos que pode user utilizando por encadeamento ou adicionando individualmente 'ouvintes', ações para ocorrências de certos eventos.

server.on('request', (request, response) => {
});

Em um desses eventos, temos 'request' que é a requisição que vamos receber. Temos uma função de listener que vai dizer o que vai ocorrer quando exista ocorrência desse evento.

    if (request.url === '/hello') {
        if (request.method === 'GET') {
            console.log('Hello, getty!');
            response.end();
        } else if (request.method === 'POST') {
            console.log('Heello, posty!');
            response.end();
        }
    }

O comportamento que tratamos é simples, não lidamos com situações de erro nem casos excepcionais, apenas lidamos com o dois casos, isso não é ideal para um produto final, mas é suficiente para quando queremos fazer uma experimentação.
Nesse caso, no endpoint /hello, requisições do tipo GET e POST entregamos diferente respostas. Vale notar que eu não estou retornando nada para quem fez as requisições, mas dentro do servidor, eu peço para exibir informações no console.

responde.end()

Documentação aqui. Para TODA resposta de um request, temos que avisar quando não há mais headers nem conteúdo para entregar, nossa mensagem está completa, para isso, devemos explicitamente com response.end() ou em alguns casos implicitamente com pipe() dizer que tudo foi entregue.

server.listen(port, function() {
console.log(`Rodando na porta ${port}`);
});

Nosso web server deve responder em uma porta, pegamos o valor da nossa constante, e pedimos para que o server escute toda requisição vinda dessa porta em particular.

#6. Testando nosso web server

Para rodar nossa aplicação, basta rodar o node com:

node main.js

Lembrando que main.js foi arquivo em javascript que escrevemos.
Se você salvou ele em um diretório em particular, você precisa rodar node assim:

node nome_do_diretorio/main.js

Se tudo deu certo, você verá no terminal a mensagem: Rodando na porta 8080. Isso significa que nosso web server local está rodando.

Se você seguiu cada passo, você após ter rodado o ngrok, ele gerou duas urls, uma com http e outra com https.
No meu caso, a url que eu recebi foi:

https://38504fd3.ngrok.io/

Copie sua url com o https do terminal e então em uma última aba do terminal, digite:

http -f GET SUA_URL/hello
ou
http -f POST SUA_URL/hello

Na sua aba do node, você receberá algum dos dois casos:

Heello, posty!

Se você fez uma requisição POST.

Hello, getty!

Ou se você fez uma requisição GET.


Em um caso mais real, lidaríamos com erro e casualidades. A maior parte dos projetos utilizam frameworks para facilitar ações recorrentes e produzir código mais rápido e eficiente ao preço de adicionar várias dependências. Apesar disso, é interessante saber como Node se comporta, antes de partir para frameworks e bibliotecas de terceiros.