Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Sua primeira request

Noções básicas de redes

Interpretação dummy para comunicação HTTP

De forma muito, mas muito, simplificada, pode-se pensar em requisições HTTP como uma forma de um computador (client) executar um procedimento remotamente por meio de um formato pré-definido (request) em outro computador (host) e obter um resultado (response).

No nosso caso, o procedimento será executar função em GO e a resposta seu retorno, mas poderia ser retornar o conteúdo de um arquivo ou realizar qualquer operação que você possa imaginar...

DNS e portas: Nomes na internet

Toda vez que você acessa um site como www.google.com ou aquele que não deve ser nomeado (sigaa.ufcg.edu.br), por exemplo, o que acontece é que o seu computador, por meio do DNS (outra sigla que vamos tratar como caixa preta) realiza a tradução desse nome para um endereço IP (192.0.2.0 ou algo assim) que pode ser usado para encontrar um computador acessível em algum lugar do mundo.

Então o seu computador envia uma requisição para o computador do endereço encontrado direcionada a uma porta, sim, precisa estar direcionado a uma porta.

No nosso caso, o servidor estará rodando na nossa própria máquina, o nome será localhost. A porta você pode escolher seu número da sorte (desde que ele seja maior que 1024, essas costumam ter uma semântica pré-definida - por exemplo, porta 80 é a porta HTTP- e requerem níveis maiores de privilégio para serem usadas).
Para acessarmos o serviço rodando na máquina local na porta 8000, usamos localhost:8000.




Não vamos se aprofundar mais que isso em HTTP ou redes, mas caso você se interesse em conhecer mais, recomendo os capítulos sobre HTTP e TCP do livro do Kurose (Computer Networking: A Top-Down Approach)

"Watch and learn before you do." - Se comunicando com outros servidores

Nesta pequena seção vamos realizar algumas chamadas para APIs externas para tentar visualizar o que acontece e ter uma noção do que vamos construir.
Vamos escolher alguma API pública para fazer algumas chamadas, eu selecionei algumas legais, você pode escolher a que te chamar mais atenção, ou qualquer outra:

APIDescrição
https://api.chucknorris.io/jokes/randomRetorna uma piada aleatória sobre o Chuck Norris.
https://rickandmortyapi.com/api/character/1Retorna dados sobre o Rick do Rick and Morty.
https://pokeapi.co/api/v2/pokemon/pikachuRetorna dados sobre o Pikachu.

Para testar no terminal, podemos usar o comando curl, ficaria: curl <url>, se você não gostar muito do que ver e tiver o jq instalado, pode rodar curl <url> | jq e ver um resultado um pouco mais amigável.

gurl: Vamos fazer uma pequena cópia do curl, recebendo uma url e imprimindo o resultado da chamada na tela!

O código ficaria assim:

package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	url := obterUrl() // obtém a url do parâmetro do terminal

	resposta, err := http.Get(url) // A boa notícia é que GO já tem toda a parte complicada pronta, então podemos só usar!!

	// Esse é o padrão de tratamento de erro em GO, as funções retornam um objeto de erro e você precisa checar ele!
	// Pode parecer um pouco verboso no começo mais deixa tudo mais explicíto e previsível, qualidades muito subestimadas em um programa.
	if err != nil {
		fmt.Println("nao foi possível se comunicar com o servidor: ", err)
		os.Exit(1)
	}

	// Só fazemos ler a reposta e imprimir na tela
	bytesDaResposta := lerResposta(resposta)
	fmt.Println(bytesDaResposta)
}

func obterUrl() string {
	// os.Args tem todos os parâmetros que passamos mais o nome do arquivo na primeira posição
	if len(os.Args) < 2 {
		fmt.Println("Usagem inválida, passe uma url como parâmetro.")
		os.Exit(1)
	}
	return os.Args[1] // os.Args[0] é o nome do arquivo, então estamos interessados no segundo elemento
}

func lerResposta(resp *http.Response) string {
	body, err := io.ReadAll(resp.Body) // Aqui lemos a resposta do servidor para um array de bytes
	resp.Body.Close()                  // Precisamos sempre fechar as "streams" em GO (isso seria discussão para um outro workshop)

	if err != nil {
		fmt.Println("Não foi possível ler a resposta: ", err)
		os.Exit(1)
	}

	return string(body) // o que é uma string se não um array de bytes?
}

Você pode brincar um pouco com diferentes URLs, experimente o que acontece se passar uma url que não existe, ou tente trocar a URI (parte dps do .com/), o que será que acontecerá se você trocar o /pikachu por /squirtle? Ou o /1 do rick and morty por /2?

Repare no início da url https://, esse é o indicador do protocolo que deve ser usado, é recomendado sempre prefixar com o protocolo. O s após http significa safe, indica que é uma variante com criptografia do http, nos nossos exemplos em localhost, vamos usar http://