Ao iniciar este projeto, você concorda com as diretrizes do Código de Ética e Conduta e do Manual da Pessoa Estudante da Trybe.
Você já usa o GitHub diariamente para desenvolver os exercícios, certo? Agora, para desenvolver os projetos, você deverá seguir as instruções a seguir. Fique atento a cada passo, e se tiver qualquer dúvida, nos envie por Slack! #vqv 🚀
Aqui você vai encontrar os detalhes de como estruturar o desenvolvimento do seu projeto a partir deste repositório, utilizando uma branch específica e um Pull Request para colocar seus códigos.
- Habilidades
- Entregáveis
- Instruções para entregar seu projeto
- Requisitos do projeto
- 1 - Criar um servidor TCP utilizando o módulo net que exiba no console todo o conteúdo recebido
- 2 - Criar um script utilizando o módulo net capaz de realizar um chamada HTTP a um server
- 3 - Criar um server TCP utilizando o módulo net capaz de responder com uma mensagem HTTP
- 4 - Criar um túnel através do Ngrok
- 5 - Configurar uma chamada HTTPS à API
iplocation
- 6 - Adicionar a estrutura de início de requisição HTTP
- 7 - Adicionar a estrutura de fim da requisição HTTP
- 8 - Identificar o endereço de IP do client
- 9 - Configurar a request HTTPS para enviar o endereço IP
- 10 - Responder o IP do client
- 11 - Responder informações extraídas através do IP do client
- 12 - Responder dados do dispositivo (client)
- 13 - Responder a request com os resources do Server
- Depois de terminar o desenvolvimento
- Revisando um pull request
- Avisos Finais
Neste projeto, verificamos se voce é capaz de:
-
Conforme aprendemos nas últimas aulas, conhecer a base do funcionamento dos computadores e das redes e suas arquiteturas nos permite utilizá-los melhor e de maneira mais eficiente, entendendo de fato o porquê de fazer algo de uma maneira ou de outra que envolva esses conceitos.
-
Diariamente estamos lidando com diversas máquinas e seus recursos, assim como as diversas redes.
-
Afinal, em nossa jornada até aqui, desenvolvemos diversos aplicativos feitos para rodar na WEB, que utilizam os diversos protocolos e outros conceitos, assim como utilizam o SO e a arquitetura dos computadores.
-
Além disso, teremos conhecimento para desenvolver soluções melhores, assim como lidar com ambientes/servidores publicados na internet, conhecendo alguns dos perigos de ter uma aplicação exposta a internet e sabendo como agregar segurança a ela.
Para entregar o seu projeto você deverá criar um Pull Request neste repositório.
Lembre-se que você pode consultar nosso conteúdo sobre Git & GitHub sempre que precisar!
Você irá refatorar parte de um servidor HTTP, porém, esse servidor não está utilizando o módulo HTTP e sim o módulo net
, ou seja, só temos a camada de transporte implementada (TCP).
O objetivo da refatoração é implementar algumas partes da camada de apresentação HTTP sem utilizar bibliotecas ou módulos para isso.
Durante o projeto, iremos passar por todas as camadas da pilha de protocolos TCP/IP
. Neste projeto, você expandirá o seu conhecimento de protocolos, explorando e aprendendo como lidar com as operações de rede!
O servidor deverá responder uma página HTML através do HTTP, mostrando algumas informações sobre o client, como dados sobre a localização, o dispositivo e a empresa provedora de internet.
Mas não se preocupe, pois por ser um conteúdo novo e representar um desafio um pouco diferente, em cada requisito haverão explicações sobre o que está acontecendo, além do que deve ser feito, para que haja ligação entre o código e a arquitetura de redes em si.
O servidor TCP responde com uma página HTML, porém, deverá ser adicionado a ele as informações de control do protocolo HTTP que representam o início e o final da response.
Você terá que utilizar o módulo net
para descobrir como é uma requisição e uma resposta HTTP de maneira "crua", ou seja, sem estar encapsulada pelo protocolo.
O código também realiza uma consulta à API pública iplocation onde, através de uma chamada HTTPS, passando um endereço de IP externo, é possível extrair algumas informações sobre o client.
Utilizaremos o ngrok para criar um túnel para o nosso projeto, tornando possível acessá-lo através da internet e não somente local. Dessa forma conseguiremos acessá-lo de outros dispositivos e conseguiremos ter acesso ao endereço de IP externo do client que fizer a requisição através da request e, então, utilizaremos esse IP para extrair as informações pela API iplocation.
Por último, alguns requisitos são dependentes uns dos outros, então recomendamos que desenvolva o projeto fazendo os requisitos na ordem em que eles forem apresentados, isso vai ajudar muito no entendimento do que está sendo proposto.
E atenção! Esse trabalho usa bastante o que vocês aprenderam nos exercícios da aula de arquitetura de redes. Usem-nos de referência, assim como a documentação do módulo NET do Node.js. E contem com nossa ajuda também no Slack! 👊
Dica: Se estiver com dificuldades para avançar no projeto, dê uma olhada nesse artigo, pois ele faz algo bem parecido com o que estamos pedindo! 😉
- Serão
7
dias de projeto. - Data de entrega para avaliação final do projeto:
18/03/2021 - 14:00h
.
- Clone o repositório
git clone https://github.com/tryber/sd-05-project-exploring-the-protocols.git
.- Entre na pasta do repositório que você acabou de clonar:
cd sd-05-project-exploring-the-protocols
- Instale as dependências
npm install
Atenção
- Crie uma branch a partir da branch
master
- Verifique que você está na branch
master
- Exemplo:
git branch
- Exemplo:
- Se não estiver, mude para a branch
master
- Exemplo:
git checkout master
- Exemplo:
- Agora crie uma branch à qual você vai submeter os
commits
do seu projeto- Você deve criar uma branch no seguinte formato:
nome-de-usuario-nome-do-projeto
- Exemplo:
git checkout -b joaozinho-project-exploring-the-protocols
- Você deve criar uma branch no seguinte formato:
- Adicione as mudanças ao stage do Git e faça um
commit
- Verifique que as mudanças ainda não estão no stage
- Exemplo:
git status
(deve aparecer listado o arquivo index.js em vermelho)
- Exemplo:
- Adicione o arquivo alterado ao stage do Git
- Exemplo:
git add .
(adicionando todas as mudanças - que estavam em vermelho - ao stage do Git)git status
(deve aparecer listado o arquivo index.js em verde)
- Exemplo:
- Faça o
commit
inicial- Exemplo:
git commit -m 'iniciando o projeto Explorando os Protocolos'
(fazendo o primeiro commit)git status
(deve aparecer uma mensagem tipo nothing to commit )
- Exemplo:
- Adicione a sua branch com o novo
commit
ao repositório remoto
- Usando o exemplo anterior:
git push -u origin joaozinho-project-exploring-the-protocols
- Crie um novo
Pull Request
(PR)
- Vá até a página de Pull Requests do repositório no GitHub
- Clique no botão verde "New pull request"
- Clique na caixa de seleção "Compare" e escolha a sua branch com atenção
- Clique no botão verde "Create pull request"
- Adicione uma descrição para o Pull Request e clique no botão verde "Create pull request"
- Não se preocupe em preencher mais nada por enquanto!
- Volte até a página de Pull Requests do repositório e confira que o seu Pull Request está criado
-
⚠ PULL REQUESTS COM ISSUES NO LINTER NÃO SERÃO AVALIADAS, ATENTE-SE PARA RESOLVÊ-LAS ANTES DE FINALIZAR O DESENVOLVIMENTO! ⚠
-
Faça
commits
das alterações que você fizer no código regularmente -
Lembre-se de sempre após um (ou alguns)
commits
atualizar o repositório remoto -
Os comandos que você utilizará com mais frequência são:
git status
(para verificar o que está em vermelho - fora do stage - e o que está em verde - no stage)git add
(para adicionar arquivos ao stage do Git)git commit
(para criar um commit com os arquivos que estão no stage do Git)git push -u nome-da-branch
(para enviar o commit para o repositório remoto na primeira vez que fizer opush
de uma nova branch)git push
(para enviar o commit para o repositório remoto após o passo anterior)
Para garantir a qualidade do código, vamos utilizar neste projeto o linter ESLint
.
Assim o código estará alinhado com as boas práticas de desenvolvimento, sendo mais legível
e de fácil manutenção! Para rodá-lo localmente no projeto, execute o comandos abaixo:
npm run lint
Para executar os testes basta executar o comando npm run test
que irá apresentar esse resultado abaixo:
Especialmente no início, quando a maioria dos testes está falhando, a saída após executar os testes é bastante poluída. Você pode desabilitar temporariamente um teste utilizando a função skip
junto à função it
. Como o nome indica, esta função "pula" um teste:
it.skip('it includes the text `Movie Cards Library` inside a h1 tag', () => {
wrapper = shallow(<Header />);
expect(wrapper.find('header h1').text()).toBe('Movie Cards Library');
});
Faça um script (exploiters/serverExploiter.js
) para criar um servidor TCP que mostre no console todo o conteúdo recebido. Depois, podemos acessá-lo pelo navegador e descobrir como é o data
de uma requisição HTTP.
Dica 1: Responda para o navegador da maneira correta usando o
socket.write
, passando oRESPONSE
como parâmetro, só queremos descobrir a estrutura da request. Não esqueca de fechar essa requisição com osocket.end
.
Além disso, volte ao conteúdo de Arquitetura de redes para retomar alguns conceitos importantes! Além do conteúdo escrito você também pode consultar o gabarito dos exercícios.
Dica 2: Logo após terminar de fazer o servidor corretamente, coloque-o online e tente acessá-lo como se fosse um site.
Você vai ver um texto no navegador, mas isso não é importante, pois o importante você receberá na console do node. Você utilizará essa resposta no próximo requisito.
Dica 3: Lembre-se de que o servidor aqui, tem sintaxe muito parecida com o socket.io, então métodos como
createServer
,on
ewrite
podem ajudar a resolver o desafio.
Dica 4: Não se esqueça do socket.end(); para fechar o socket. Sem ele sua requisição ficará em loop infinito e será impossível testar. (CAUTION: request is not finished yet!)
[Será validado que ao fazer a request e acessar o chrome irá mostrar os dados no console]
Crie um novo script (exploiters/clientExploiter.js
), que utilize a request extraída no requisito anterior (1), realizando as devidas modificações para fazer uma request HTTP à página do Google (google.com
) e, então, exiba no console a resposta "crua" dada pelo servidor da Google. Ou seja, crie uma requisição HTTP “na mão” usando como base a resposta de saída da requisição do requisito 1. Você irá copiar o response do requisito anterior para montar sua requisição neste requisito. Você pode utilizar, pra fazer essa requisição "na mão", o client.write
do NET
Aqui descobrimos como é uma response HTTP sem encapsulá-la.
Dica 1: Na request (que é a saída do console do node do primeiro requisito) existem características que indicam ao HTTP onde a request finaliza, então, tenha certeza que pegou todo o conteúdo, inclusive quebras de linhas. Para representar as quebras de linhas você pode utilizar "template strings".
Dica 2: Ao pegar a request, gaste algum tempo lendo a mesma e perceberá que uma das propriedades da request, a Host tem o endereço que você tentou acessar antes.
Dica 3: Lembre-se de que o cliente aqui, tem sintaxe muito parecida com o socket.io, então métodos como
connect
,on
ewrite
podem ajudar a resolver o desafio.
[Será validado que ao fazer a request irá mostrar os dados no console]
Utilizando a response capturada no requisito anterior (2), faça um server (exploiters/httpServer.js
) que responda uma página HTML, faça as devidas modificações na response para que retorne uma mensagem com o status code HTTP 200.
Dica 1: Você pode começar fazendo um servidor, será muito parecido sintaticamente com o que fizemos no requisito 1, porém agora vamos ter que passar uma requisição que esteja corretamente montada para o método
write
.
Dica 2: Você precisa de um retorno código 200 para que tudo funcione bem, você pode conseguir um modelo de response para utilizar aqui de diversas maneiras, como por exemplo lendo o material que passamos mais acima no artigo. A grande diferença desse requisito para o requisito 1, é que ao acessar esse servidor via navegador, ele retorne o HTML que você colocar para ser retornado.
Dica 3: Lembre-se de que o servidor aqui, tem sintaxe muito parecida com o socket.io, então métodos como
createServer
,on
ewrite
podem ajudar a resolver o desafio.
[Será validado que ao fazer a request e acessar a url irá mostrar o texto "Protocolos"]
O 'ngrok' é nada mais nada menos do que um "túnel", onde a função dele é redirecionar conexões externas para o seu localhost. Ou seja, você consegue com ele, por exemplo, rodar um projeto que está em 'localhost' na rede externa e mostrar para outras pessoas.
Dessa forma, crie um túnel para seu localhost
, utilizando o Ngrok
. Em seguida, acesse-o de diferentes dispositivos de rede para testar o funcionamento do nosso projeto.
Um túnel é um redirecionador, ele pode redirecionar IPs e portas para outros IPs e portas, no nosso caso, iremos utilizar a partir de agora o endereço que o ngrok
nos fornecer para acessar o nosso servidor net
.
Outro ponto importante é estar sempre atento a porta que estamos expondo do nosso localhost
para a rede externa via túnel, que deve ser sempre igual a porta utilizada no servidor net
.
Adicione no arquivo instructions.json
o passo-a-passo com os comandos ngrok
e Node.js
para executar e realizar a publicação do projeto.
Adicione no arquivo instructions.json
na chave token o seu token atráves dele que o avaliador irá usar o ngrok.
Dica 1: Consulte o
getting started - setup
na página para instalar ongrok
corretamente.
Dica 2: Lembre-se que a porta com que devemos rodar o
ngrok
deve ser a porta que o servidor que queremos acessar está rodando! Então sempre verifique a porta que está utilizando no momento.
Dica 3: Existe uma versão do ngrok específica do seu sistema operacional, adicione na pasta raiz do projeto.
Dica 4: O ngrok só pode abrir um tunel por conta, então tome alguns cuidados:
-
Primeiro verifique que não tem nenhum tunel aberto na sua maquina.
-
Faça um push por vez e espere terminar de rodar para fazer outro push.
-
Verifique que você está subindo o
ngrok
da versão linux para o github pois ele é a versão correta para o avaliador funcionar.
[Será validado se os comandos estão dentro do arquivo instruction.json]
No projeto temos o arquivo location.js
, responsável por fazer a request HTTPS à API iplocation
. Altere o objeto options
desse arquivo para a seguinte configuração:
-
hostname: "iplocation.com";
-
port: Preencha com a porta padrão HTTPS;
-
path: '/';
-
method: POST;
-
headers: Adicione o header "Content-Type", com o valor "application/x-www-form-urlencoded".
Dica 1: Aqui vamos escrever as informações necessárias para fazer uma requisição, então é só preencher o objeto corretamente.
Dica 2: Nesse momento, não dá para testar o requisito, pois faltam informações, se prestarmos atenção ao código do
location.js
, veremos que a funçãogetLocationInfos
recebe um parâmetro que não está sendo utilizado. Os próximos requisitos utilizarão esse parâmetro e aí sim esse requisito aqui poderá ser testado.
Dica 3: Apesar de poder subir várias instâncias do
ngrok
, suba as instâncias conforme for necessitando em cada requisito, pois a cada requisito a porta pode mudar.
Dica 4: Caso esteja recebendo um erro de
connection refused
no navegador, verifique a porta do seu túnel.
[Será validado que foi configurada a chamada do iplocation
]
No arquivo index.js
do projeto, altere a variável startOfResponse
para receber a estrutura que descobrimos anteriormente, da mesma forma que fizemos no requisito 3. Faça as devidas alterações para que a resposta tenha os seguintes valores:
-
Versão 1.1 do protocolo HTTP;
-
Status code
HTTP 200
; -
Header "Content-Type" como "text/html; charset=UTF-8".
Dica 1: Antes de começar a trabalhar nesse requisito, leia o código do arquivo
index.js
com atenção, ele vai lhe dar pistas sobre o que você precisará fazer aqui e o contexto do código a ser escrito.
Dica 2: Mais uma vez, não esqueça das quebras de linhas 😉. Não é necessário nenhum outro header além do "Content-Type".
Dica 3: Ainda precisa de mais código para funcionar, continue adiante!
[Será validado que foi adicionado a estrutura da requisição no startOfResponse]
Ainda no arquivo index.js
, altere a variável endOfResponse
para receber a estrutura utilizada pelo HTTP para informar o fim de uma request.
Dica 1: Ainda precisa de mais código para funcionar, continue adiante!
[Será validado que foi adicionado a estrutura da requisição no endOfResponse]
Utilizando a função getHeaderValue
, extraia do data o header X-Forwarded-For
. Esse header será adicionado pelo nosso túnel automaticamente, contendo o endereço de IP do client. Passe esse IP para a função getLocationInfos
, para que possamos extrair dados através dele.
Dica 1: Converta o data para String antes de extrair os headers.
Dica 2: A função
getLocationInfos
recebe como parâmetro a variávelclientIP
, então utilize a funçãogetHeaderValue
passando as informações e o header que precisamos do valor.
Dica 3: Para poder ver o header que estamos falando no requisito, é necessário criar o túnel com o
ngrok
para que esse header exista na requisição e seu valor possa ser capturado.
Dica 4: Caso tenha dificuldade em entender a função
getHeaderValue
, experimente usar algunsconsole.log
nas variáveis internas da função!
Dica 5: Ainda falta um requisito para finalizarmos a requisição e por isso, não conseguiremos testar agora, tenha a certeza de ter colocado a mensagem de texto que foi pedida e passe para o próximo requisito!
[Será validado que foi adicionado o código para pegar endereço de IP]
Agora, no arquivo location
, antes de finalizar a request, adicione uma linha que envie o ip do cliente, utilizando o método write
da requisição. A API espera receber a seguinte mensagem texto: "ip=CLIENT_IP".
Dica 1: A API espera receber um body sem nenhuma formatação. Envie a string conforme exemplo, substituindo o
CLIENT_IP
pela variável recebida no método.
Dica 2: Atente-se para o fato que em nosso código,
responses
são chamadas deres
erequests
são chamadas dereq
.
Dica 3: Se tudo foi feito corretamente até aqui, ao ir até o navegador você terá uma surpresa bem positiva! Caso nada apareça, verifique seus headers, podem estar faltando partes importantes deles lá, verifique-os.
[Será validado que foi adicionado a request no arquivo location]
Adicione mais um comando write
, na estrutura do response do arquivo index.js
, para responder com o endereço de IP do client extraído no requisito 8.
- Adicione uma tag
data-testid="ip"
junto ao texto do client_ip.
[Será validado que ao acessar a url sera possível visualizar o ip do client]
Adicione mais comandos write
, na estrutura do response. A resposta da API iplocation
deverá conter as seguintes informações:
-
Cidade;
- E adicione a tag
data-testid="city"
para o front.
- E adicione a tag
-
Código Postal (da cidade);
- E adicione a tag
data-testid="postal_code"
para o front.
- E adicione a tag
-
Região e nome da região;
- E adicione a tag
data-testid="region"
para o front.
- E adicione a tag
-
Nome do país;
- E adicione a tag
data-testid="country"
para o front.
- E adicione a tag
-
Companhia (nome da provedora de internet);
- E adicione a tag
data-testid="company"
para o front.
- E adicione a tag
[Será validado que as informações da localização do cliente serão exibidas na tela]
Utilizando também a função para extrair informações dos headers da request, extraia o conteúdo do header User-Agent
e o adicione na estrutura da response.
Dica: Converta o data para String antes de extrair os headers.
- E adicione a tag
data-testid="device"
para o front.
[Será validado se que ao acessar a tela listou os dados do dispositivo]
Ao identificar a correspondência do requisito anterior (12), utilizando os módulos nativos do node.js
para chamadas ao sistema operacional, responda, ao invés dos dados do client, dados do server:
-
O Sistema Operacional, sua versão e arquitetura;
- E adicione a tag
data-testid="arch"
para o front.
- E adicione a tag
-
Informações sobre a CPU - quantidade de cores, o modelo e velocidade de cada um;
- E adicione a tag
data-testid="cpu"
para o front.
- E adicione a tag
-
Quantidade de memória total em gigabytes (GB).
- E adicione a tag
data-testid="memory"
para o front.
- E adicione a tag
Dica: Pode adicionar na mesma requisição do
getLocationInfos
do arquivoindex.js
.
Para "entregar" seu projeto, siga os passos a seguir:
- Vá até a página DO SEU Pull Request, adicione a label de "code-review" e marque seus colegas
- No menu à direita, clique no link "Labels" e escolha a label code-review
- No menu à direita, clique no link "Assignees" e escolha o seu usuário
- No menu à direita, clique no link "Reviewers" e digite
students
, selecione o timetryber/students-sd-05
Se ainda houver alguma dúvida sobre como entregar seu projeto, aqui tem um video explicativo.
⚠ Lembre-se que garantir que todas as issues comentadas pelo Lint estão resolvidas! ⚠
À medida que você e as outras pessoas que estudam na Trybe forem entregando os projetos, vocês receberão um alerta via Slack para também fazer a revisão dos Pull Requests dos seus colegas. Fiquem atentos às mensagens do "Pull Reminders" no Slack!
Use o material que você já viu sobre Code Review para te ajudar a revisar os projetos que chegaram para você.
Ao finalizar e submeter o projeto, não se esqueça de avaliar sua experiência preenchendo o formulário. Leva menos de 3 minutos!
Link: FORMULÁRIO DE AVALIAÇÃO DE PROJETO
O avaliador automático não necessariamente avalia seu projeto na ordem em que os requisitos aparecem no readme. Isso acontece para deixar o processo de avaliação mais rápido. Então, não se assuste se isso acontecer, ok?