Tutorial de fundamentos web

Criado por Tim McEwan, @tjmcewan Traduzido por Bárbara Barbosa, @bahbbc

Objetivo

Você já imaginou como a informação sai e entra do seu nagevador web? Nesse tutorial nos vamos ver como tudo isso funciona explorando o HTTP.

Nós vamos usar o Sinatra como ferramenta para demostrar alguns principios básicos. O sinatra é um pequeno framework para criar aplicações web em Ruby como o mínimo de esforço. Você pode encontrar uma lista de coisas construídas com Sinatra aqui.

O sinatra é diferente do Rails. Os dois são frameworks que nos ajudam a escrever aplicativos web, mas o Sinatra contém menos recursos e menos mágica.

Introdução

HTTP é usado para enviar informação através de uma aplicação (como o seu app do Rails Girls) e um navegador. O básico de uma cominicação com HTTP é o par requisição/resposta. Requisições são enviadas do navegador para o servidor (ex. o seu app) e a resposta é enviada de volta para o servidor para o seu navegador para um usuário ver.

Para fazer uma requisição no navegador, você precisa usar uma URL. Uma URL contém várias informações sobre qual informação você está requisitando então o servidor poderá te enviar a resposta correta.

Uma URL contém:

Quebra de uma URL

URLs revelam o recurso que você quer, mas a ação que precisa ser realizada naquele recurso precisa ser especificada usando verbos HTTP.

O verbos HTTP mais comuns são

Você deve ter usado todos esses verbos no seu app do Rails Girls quando você fez ele mostrar, criar, editar e deletar posts ou notas.

Um request para um servidor precisa incluir tanto a URL e o verbo HTTP.

Nos exercícios seguintes você irá construir uma pequena aplicação de um café que usa uma combinação de pastas de recursos e verbos HTTP para demostrar como os navegador se comunicam com a sua aplicação.

O seu app vai ficar parecido com esse no navegador:

Sinatra Coffee App

0. Instalar o Sinatra - “Olá Mundo”

Vamos começar rodando o Sinatra.

No seu terminal, instale a gem:

gem install sinatra
gem install sinatra-contrib

1. “Olá Mundo”

Crie um arquivo chamado app.rb e cole o seguinte código no seu editor de texto:

require "sinatra"
require "sinatra/reloader"

get "/" do
"Olá mundo!"
end

E no seu terminal, cole o código abaixo:

ruby app.rb

Veja o seu site em: http://localhost:4567

A informação aparecendo no seu navegador é a resposta de uma requisição GET.

Quando você digita http://localhost:4567 você está enviando uma requisição GET para o seu servidor Sinatra.

O que você vê no navegador é a resposta do seu servidor Sinatra.

Quando você escreve “/”, você só está especificando a url raiz, mas você pode criar qualquer caminho que você queira.

No mesmo arquivo, tente criar mais páginas para visitar, usando a mesma sintaxe do bloco acima. Você pode adicionar quantas páginas quiser, e fazê-las mostrar o que você quiser.

e.g.

get "/nome-da-pagina" do
 "Esse é o texto da página"
 end

Se você quiser você pode apertar Ctrl+C no seu terminal para parar o seu app. (Exatamente como o seu app Rails!), contudo você não precisa reiniciar o seu servidor para ver as mudanças.

Se você ficar travada, garanta que o seu app.rb parece com esse aqui.

3. Formulário HTML - Parâmetros

Para começar a listagem de cafés no seu app, nos vamos precisar de um formulário HTML para enviar qual café nos queremos e quando ele custa.

Isso significa enviar uma requisição para o servidor Sinatra, incluindo alguma informação.

Para enviar informação para o servidor, nós podemos usar um formulário.

Substitua o seu get "/" do exemplo anterior por:

get "/" do
"
<html>
<body>
<form action='/' method='get'>
Café: <input name='cafe'>
Valor: <input name='valor'>
<button type='submit'>Adicionar café</button>
</form>
<!-- cafes vao aqui -->
</body>
</html>
"
end

Para simplificação, esse formulário envia a informação para a mesma URL (“/”).

Atualize o seu navegador e veja o formulário que você acabou de criar.

Agora vamos ver o que o navegador enviou ao servidor quando você submeteu o formulário. Coloque um pouco de texto no formulário e clique no botão ‘Adicionar café’. Verifique os logs do Sinatra no seu terminal e você deve ver algo assim:

GET /?cafe=flat+white&valor=3.50 HTTP/1.1

Instrutor(a): Falar sobre de onde ve os nomes dos parâmetros e o que faz o ponto de interrogação.

Se não deu muito certo, certifique-se de que o seu código parece com esse código.

4.Inspetor Web - Cabeçalho de requisição

No seu navegador, abra o console web. (Para a maioria dos navegador, o console pode ser acessado assim: clique com o botão direito em qualquer lugar da página e selecione “Inpecionar Elemento”.) Eu recomendo que você use o Chrome para isso; se você estiver usando o Chrome, olhe a aba ‘Network’.

Atualize o seu navegador, então clique na linha localhost no inspetor web, e então na aba cabeçalhos, clique em ver código fonte. Você deve ver algo similar a isso:

GET / HTTP/1.1
Host: localhost:4567
Connection: keep-alive
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.70 Safari/537.36
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8

Instrutor(a): Explicar o que são os cabeçalhos (headers) HTTP e o que eles significam.

A parte mais importante está na primeira linha, que separa o verbo HTTP da URL que foi chamada.

Nota: Se o Sinatra disser “backup from WEBrick”, o servidor embutido do Ruby, então pode ser que você veja multiplas requisições GET a cada atualização sua. Apenas uma requisição está sendo processada, você pode ignorar a outra tranquilamente.

5. Variável global

Então, o nosso formulário está enviando a informação do café ao nosso app, mas nós não estamos fazendo nada com ela ainda. Nós devemos salvar a informação do café depois que ela for enviada para o servidor.

Para simplificar, vamos guardar os detalhes do café em uma variável. Assim eles estarão disponíveis entre requisições, para isso nós usaremos uma variável global. Essa é uma versão drasticamente simplificada do que o Rails chama de camada de Modelo.

Adicione o código abaixo ao seu arquivo app.rb (a convenção dita que deve ser próximo ao topo, abaixo das linhas de require):

$cafes = []

Isso criará um array vazio quando o seu app inicializar.

Dica Essa variável global não ficará por perto por muito tempo - ela se toranará um array vazio toda vez que o servidor reiniciar. Como nós estamos usando o reloader (recarregador) do Sinatra, isso acontecerá toda vez que você salvar o seu arquivo app.rb. Não se preocupe, ele servirá aos nossos propósitos.

6. Recebendo informação - Salvando cafés

Agora nós precisamos colocar a informação dentro do array $cafes quando a requisição for recebida. Quando você completa o formulário e clique no botão para enviar, lembre-se que a informação fica no final da URL, após o ?, para ser enviada de volta ao servidor.

O Sinatra captura essa informação do final da URL e a torna disponível como um hash chamado params. Por exemplo:

 params = {cafe = 'cafe com leite', valor ='2'}

Você vai precisar escrever um pouco de código para retirar a informação do hash de params e adicioná-los a sua variável $cafes.

Antes de começarmos, primeiro substitua <!-- cafes vao aqui --> no seu formulário por:

#{ $cafes.inspect }

Isso irá mostrar a variável $cafes no HTML do seu navegador para podermos dizer se os café estão sendo adicionados a sua variável $cafes (i.e. que o seu código está funcionando).

Dica Sua variável global é um array, então se você não souber o que fazer, olhe a Documentação de array do Ruby para buscar mais informações sobre como adicionar informações para um array.

Se você estiver travada, clique aqui.

Se você está guardando seus parâmetros corretamente, você deve conseguir recarregar a paǵina e ver que um novo hash foi adicionado ao array $cafes a cada vez.

6. Arrumando tudo

Aquele grande pedaço de HTML no seu código get está dificultando a visualização do que o seu app faz. Vamos movê-lo para o seu próprio método.

Tire o formulário HTML do seu código get e cole em um método chamado template (mantenha todo o seu código no mesmo arquivo). Tipo assim:

def template
# Coloque o seu formuário HTML aqui
end

Agora substitua o formulário do seu código get por uma simples chamada ao método template, assim:

get "/" do
$cafes << params
template
end

Isso também tornará fácil reusar o formulário, caso a gente precise depois.

Dica Check here se algo der errado.

7. Indo além do GET

Como você viu na seção de salvar cafés, se você atualizar o seu navegador, o seu app adiciona a informação na variável global $cafes repetidamente. Isso acontece porque estamos guardando os parâmetros da URL cada vez que o nosso código get é requisitado.

Precisamos mencionar que as requisições GET não devem fazer coisas que adicionem informação ao nosso app - mesmo que funcione, como nessa instância, é muito fácil que efeitos colaterais não intencionados ocorram. Nesse caso é melhor usar uma requisição POST.

Lembre-se que as requisições GET estão querendo buscar um recurso, enquanto as requisições POST querem criar um recurso.

Então armados com esse conhecimento, vamos mudar o método do nosso formulário para POST:

Uh oh! Bem vindo a adorável página de erro do Sinatra, se você ainda não a viu hoje. A mensagem no final deve dizer algo assim:

Try this:
post '/' do
 "Hello World"
end

Essa é a maneira do Sinatra de te contar que a rota que você requisitou não existe. Você talvez conheça isso como o erro HTTP número 404: página não encontrada

8. Adicionar a Post

Vamos adicionar o nosso código post no Sinatra (não remove o código de get!)

Como usual, você pode verificar o seu progresso por aqui.

Agora se você atualizar a página depois de submeter um café, você deverá ver um aviso do navegador avisando que ele precisa resubmeter o formulário para carregar a página:

Chrome's confirm resubmission dialog

Você já deve ter visto isso algumas vezes quando você submteu formulários online. Ter esse aviso nos alerta as consequências da nossa atualização e nos provavelmente evitaremos adicionar o mesmo café várias vezes.

Lembre-se que as requisições GET querem buscar um recurso, enquanto as requisições POST querem criar um recurso. Se você atualizar a página em uma requisição GET, você está simplesmente pedindo para ver a mesma página várias vezes, o que normalmente não será um problema.

Contudo, se você atualizar a página em uma requisição POST, isso significa que você está reenviando a requisição POST, e pode estar criando um novo recurso cada vez que você atualiza. É por isso que o navegador te dá um aviso antes de permitir que você faça isso.

9. Adicionando um redirect

Para contornar esse problema de resubmissão de formulário, vamos avisar o navegador para carregar uma página diferente assim que ele receber a resposta do nosso POST. Nós faremos isso usando uma resposta HTTP especial conhecida como “redirect”.

Ao invés de outra chamada ao nosso método template, nós podemos redirecionar o navegador para outro lugar.

No Sinatra é algo assim:

redirect "/"

Tente primeiro, e depois clique aqui.

Isso enviará uma resposta de redirect especial (HTTP 303) com um cabeçalho de location que especifica para onde o navegador deve ir:

HTTP/1.1 303 See Other
<…>
Location: http://localhost:4567/

Para ver isso em ação, você pode ver o Inspetor web do Chrome (na aba Rede) e enviar para o seu app um café:

Chrome's network tab showing a post/redirect/get

A primeira linha mostra o navegador enviando o formulário usando a requisição POST. A resposta que ele recebe é um HTTP 303, contendo o cabeçalho Location. Ele então dispara uma requisição GET para aquela localização (que corresponde a nossa rota raiz, “/”) e renderiza a resposta que ele pega de lá - que é o nosso template HTML.

Agora você pode atualizar tudo o que quiser e o que você está fazendo é requisitando usando GET, não POST. O seu navegador não precisa ter mais ter que reenviar o formulário para aparecer aquela página.

Esse é o fim do tutorial - você fez um excelente trabalho!

Obrigada por jogar!

Guias adicionais

Se isso foi rápido e você quiser continuar, você pode ver:


Outros Guias