a página morta
this post is only available in português
A Fubá já tem voz: o servidor responde, o curl conversa com ela. Só que uma frase em texto puro não é telinha bonita, e telinha bonita era o pedido original. Então hoje é dia! A jhujuba, que de telinha entende, pode me julgar - e a pergunta que consigo imaginar é: “fiz os botões… por que eles não fazem nada?”. Junto do “pô, sem querer dar pitaco, mas deixa X desse jeito aqui…”
a telinha
Primeiro, a telinha. Cria a pasta priv/static/ e salva esse HTML+CSS no arquivo index.html:
<!-- priv/static/index.html -->
<body>
<main>
<p class="carinha">(  ̄^ ̄)</p>
<h1>Fubá</h1>
<p class="humor">tá chatinha… cadê o café?</p>
<div class="medidores">
<div class="medidor"><span>biscoito</span><span class="barra">■■■□□</span></div>
<div class="medidor"><span>cafeína</span><span class="barra baixa">■□□□□</span></div>
<div class="medidor"><span>carinho</span><span class="barra">■■□□□</span></div>
<div class="medidor"><span>energia</span><span class="barra">■■■■■</span></div>
</div>
<div class="acoes">
<button>🍪 biscoito</button>
<button>☕ café</button>
<button>🫶 cafuné</button>
<button>🍃 espaço</button>
</div>
</main>
</body>
Isso é só o body - o arquivo completo tem um <style> em cima com as cores e o desenho do cartão, e tá no repositório pra você copiar inteiro. Ou melhor: faz a sua. As cores, a fonte, as carinhas… a Fubá é minha, a página é sua.
Duas coisas pra reparar já nesse HTML. A carinha é (  ̄^ ̄) - chatinha - e a cafeína tá em um quadradinho só. Não porque a Fubá esteja assim: porque alguém escreveu isso no HTML, à mão, fixo. E os quatro botões são só <button>: desenho de botão, que não fazem nada. Lembra disso.
o que é um arquivo estático
Até aqui, a resposta do servidor era uma frase digitada dentro do código Elixir. Uma página web é diferente: é um arquivo de verdade, guardado em no computador que o servidor tá rodando, e que é lido e devolvido do jeito que está, sem mexer em nada. Por isso o nome: estático. O mesmo arquivo, igualzinho, pra todo mundo que pedir, hoje e amanhã.
E o navegador? Lá no post passado ele era “um cliente HTTP que sabe desenhar”. Pois é aqui que ele desenha: pede a página, recebe texto HTML no corpo da resposta, e transforma aquele texto no cartãozinho roxo com botões. O servidor não desenha nada - ele só entrega o papel.
A pasta priv/ é o endereço oficial dessas coisas em projeto Elixir: arquivos que não são código mas viajam junto com a aplicação. Página, imagem, fonte - mora em priv.
encadeando plugs
Como o nosso Plug aprende a deolver arquivo? Não aprende - a gente contrata um colega pra ele. O novo lib/fuba_web/plug.ex:
defmodule FubaWeb.Plug do
use Plug.Builder
plug Plug.Static, at: "/", from: :fuba
plug :nao_achei
def nao_achei(conn, _opts) do
send_resp(conn, 404, "nada aqui, uai")
end
end
Mudou tudo, então devagar. O use Plug.Builder transforma o módulo numa esteira de plugs: cada linha plug é uma estação, e a requisição passa por elas de cima pra baixo (que nem o casamento de padrão em funções com múltiplas cláusulas). A conn entra na primeira estação, que pode responder na hora (e a esteira para ali) ou passar adiante pra próxima. Sabe o init/1 e o call/2 que a gente escreveu na mão no post passado? O Plug.Builder escreve eles pra gente, com essa esteira dentro.
A primeira parada é o Plug.Static, um plug pronto da biblioteca: ele procura o caminho pedido entre os arquivos estáticos. O at: "/" diz “atende pedidos a partir daqui, da /“, e o from: :fuba diz “procura na pasta priv/static da aplicação :fuba“. Pediu /index.html? Ele acha o arquivo, lê do disco e responde com 200. Não achou? Ele não inventa nada - só deixa a requisição seguir viagem.
E aí entra a segunda parada: nao_achei, uma função nossa. Se a requisição chegou até ela, é porque nenhum arquivo existia, então ela responde 404 com um “nada aqui, uai”. Repara nos dois jeitos de plugar: Plug.Static é um módulo plugado (tem init/1 e call/2 lá dentro, como o nosso Plug do post passado), e :nao_achei é uma função plugada, pra quando for algo simples.
vendo a página
Sobe o servidor (iex -S mix) e abre o navegador em http://localhost:4000/index.html.
A Fubá na tela. Roxa, com carinha de poucos amigos, quatro medidores, quatro botões. A telinha bonita existe!
Agora clica no botão de café.
…
Nada. Clica de novo. Nada.
por que o botão não faz nada?
São três respostas, porque são três motivos diferentes:
-
O botão é só um desenho. Um
<button>sozinho não faz nada. Nada no HTML diz “quando clicarem aqui, avisa o servidor”. Ele é uma maçaneta pintada na parede. -
A página é uma foto, não a coelhinha. A carinha chatinha, a cafeína baixa - tá tudo escrito à mão no arquivo. A Fubá de verdade, aquela struct viva do post 2, continua existindo só no
iex. O servidor nem sabe que ela existe: nenhuma linha doFubaWebimporta oFuba.Cuidado. -
O servidor entrega sempre o mesmo papel. Cada pedido recebe o arquivo idêntico. Mesmo que a coelhinha mudasse, a página não mudaria junto - ela nasceu pronta e morre igual.
Ou seja: a página está morta. Bonita, servida de verdade pela internet, e completamente desligada da coelhinha. E cada um desses três motivos vai ser um post futuro.
fechou?
Três critérios:
-
http://localhost:4000/index.htmlabre a página no navegador, com os quatro botões. -
curl -i localhost:4000/index.htmlmostra o200 OKe o HTML no corpo. -
Qualquer caminho que não existe -
curl localhost:4000/banana- responde404com o “nada aqui, uai”.
E o bônus pra pensar antes do próximo post: se a página mostrasse a Fubá de verdade, com os medidores dela agora, o que precisaria acontecer entre o pedido chegar e o HTML sair?
Fechou? No próximo post a foto vira retrato vivo: o HTML deixa de ser arquivo parado e vira uma função do estado da coelhinha - é o tal do template (HTML dinâmico).