Introdução: Por que Rust é uma excelente escolha para requisições HTTP
\nRust é uma linguagem de programação de sistemas que ganhou popularidade devido à sua segurança, desempenho e ausência de coletor de lixo. Se você está desenvolvendo uma aplicação de rede, um web scraper ou um microsserviço, saber como fazer requisições HTTP corretamente em Rust é uma habilidade obrigatória. Neste artigo, vamos abordar como criar um cliente HTTP completo em Rust usando a biblioteca reqwest, que é o padrão de facto para trabalhar com HTTP no ecossistema Rust.
Vamos percorrer o caminho desde a instalação das dependências até o tratamento de erros e o trabalho com JSON. Ao final do artigo, você será capaz de escrever clientes HTTP robustos e rápidos em Rust que não falharão em produção.
\n\nInstalação e configuração do projeto
\nO primeiro passo é criar um novo projeto e adicionar a dependência reqwest com suporte a assincronia e JSON.
cargo new rust_http_client\ncd rust_http_client\nAbra o Cargo.toml e adicione:
[dependencies]\nreqwest = { version = "0.12", features = ["json"] }\ntokio = { version = "1", features = ["full"] }\nserde = { version = "1", features = ["derive"] }\nserde_json = "1"\nVamos explicar cada dependência:
\n- \n
- reqwest — o cliente HTTP principal. A flag
jsonativa o suporte para serialização/desserialização. \n - tokio — o runtime assíncrono do Rust. As requisições HTTP no
reqwestsão assíncronas por padrão. \n - serde / serde_json — para trabalhar com JSON (estruturas, serialização). \n
Agora está tudo pronto para escrever o código.
\n\nRequisição GET básica: obtendo dados do servidor
\nVamos começar com uma requisição GET simples. Criaremos uma função que obtém dados de uma API pública e os exibe no console.
\nuse reqwest::Error;\n\n#[tokio::main]\nasync fn main() -> Result<(), Error> {\n let url = "https://jsonplaceholder.typicode.com/posts/1";\n let response = reqwest::get(url).await?;\n\n println!("Status: {}", response.status());\n\n let body = response.text().await?;\n println!("Corpo da resposta:\\n{}", body);\n\n Ok(())\n}\nO que está acontecendo aqui:
\n- \n
- Usamos o macro
#[tokio::main]para executar a função assíncrona. \n reqwest::get(url).await?executa a requisição GET. O sinal?propaga o erro se a requisição falhar. \nresponse.status()retorna o status HTTP (por exemplo, 200 OK). \nresponse.text().await?extrai o corpo da resposta como uma string. \n
Execute o código com o comando cargo run. Você verá um objeto JSON com os dados do post.
Adicionando cabeçalhos e parâmetros de requisição
\nEm aplicações reais, muitas vezes é necessário passar cabeçalhos (por exemplo, chave de API) ou parâmetros de consulta. Veja como fazer isso:
\nuse reqwest::Client;\nuse std::collections::HashMap;\n\n#[tokio::main]\nasync fn main() -> Result<(), reqwest::Error> {\n let client = Client::new();\n\n let mut params = HashMap::new();\n params.insert("userId", "1");\n\n let response = client\n .get("https://jsonplaceholder.typicode.com/posts")\n .header("Accept", "application/json")\n .query(¶ms)\n .send()\n .await?;\n\n let posts: serde_json::Value = response.json().await?;\n println!("Número de posts: {}", posts.as_array().unwrap().len());\n\n Ok(())\n}\nPontos-chave:
\n- \n
- Criamos um
Client— este é um cliente HTTP reutilizável com um pool de conexões. Sempre use Client em vez de chamadas diretas areqwest::getpara código em produção. \n - O método
.header()adiciona um cabeçalho. \n .query()aceita um dicionário de parâmetros e codifica a URL automaticamente. \n.json()desserializa imediatamente