Comment créer une requête HTTP depuis Rust?

Comment puis-je faire une requête HTTP depuis Rust? Je n’arrive pas à trouver quoi que ce soit dans la bibliothèque principale.

Je n’ai pas besoin d’parsingr la sortie, il suffit de faire une demande et de vérifier le code de réponse HTTP.

Des points bonus si quelqu’un peut me montrer comment encoder les parameters de requête sur mon URL!

Mise à jour: Cette réponse fait référence à une histoire assez ancienne. Pour les meilleures pratiques actuelles, veuillez plutôt regarder la réponse d’Isaac Aggrey .


J’ai travaillé sur rust-http , qui est devenu la bibliothèque HTTP de facto pour Rust (Servo l’utilise); c’est loin d’être complet et très mal documenté à l’heure actuelle. Voici un exemple de demande et de création de code:

extern mod http; use http::client::RequestWriter; use http::method::Get; use http::status; use std::os; fn main() { let request = RequestWriter::new(Get, FromStr::from_str(os::args()[1]).unwrap()); let response = match request.read_response() { Ok(response) => response, Err(_request) => unreachable!(), // Uncaught condition will have failed first }; if response.status == status::Ok { println!("Oh goodie, I got me a 200 OK response!"); } else { println!("That URL ain't returning 200 OK, it returned {} instead", response.status); } } 

Exécutez ce code avec une URL comme seul argument de ligne de commande et il vérifiera le code d’état! (HTTP uniquement; pas de HTTPS.)

Comparez avec src/examples/client/client.rs pour un exemple qui en fait un peu plus.

rouille-http suit la twig principale de la rouille. À l’heure actuelle, cela fonctionnera dans le tout nouveau Rust 0.8, mais il est probable que des changements se produiront bientôt. En fait, aucune version de rust-http ne fonctionne avec Rust 0.8 – il y a eu un changement brusque qui ne peut pas être corrigé dans les règles de confidentialité juste avant la publication, laissant quelque chose dont la rouille http dépend dans extra :: url inaccessible. Cela a été corrigé depuis, mais cela laisse rouille-http incompatible avec Rust 0.8.


En ce qui concerne le codage de la chaîne de requête, cela devrait se faire avec extra::url::Query (un typedef pour ~[(~str, ~str)] ). Fonctions appropriées pour les conversions:

  • extra::url::query_to_str

  • extra::url::query_from_str (désolé, extra::url::query_from_str ne peux pas l’utiliser pour l’instant car c’est privé. PR pour le rendre public à venir. En attendant, ce lien ne devrait pas fonctionner, il est uniquement disponible à cause de https : //github.com/mozilla/rust/issues/7476 .)

Le moyen le plus simple de faire du HTTP dans Rust est reqwest . C’est un wrapper pour rendre Hyper plus facile à utiliser.

Hyper est une bibliothèque HTTP populaire pour Rust et utilise deux bibliothèques: la boucle d’événement de Tokio pour faire des requêtes non bloquantes et des futures pour les futures / promesses. Un exemple basé sur Hyper est ci-dessous et est largement inspiré par un exemple dans sa documentation .

 // Rust 1.19, Hyper 0.11, tokio-core 0.1, futures 0.1 extern crate futures; extern crate hyper; extern crate tokio_core; use futures::{Future}; use hyper::{Client, Uri}; use tokio_core::reactor::Core; fn main() { // Core is the Tokio event loop used for making a non-blocking request let mut core = Core::new().unwrap(); let client = Client::new(&core.handle()); let url : Uri = "http://httpbin.org/response-headers?foo=bar".parse().unwrap(); assert_eq!(url.query(), Some("foo=bar")); let request = client.get(url) .map(|res| { assert_eq!(res.status(), hyper::Ok); }); // request is a Future, futures are lazy, so must explicitly run core.run(request).unwrap(); } 

Dans Cargo.toml :

 [dependencies] hyper = "0.11" tokio-core = "0.1" futures = "0.1" 

Pour la postérité, j’ai laissé ma réponse originale ci-dessous, mais voir ci-dessus pour une mise à jour de Rust 1.19 (dernière version stable à ce jour).

Je crois que ce que vous cherchez se trouve dans la bibliothèque standard . maintenant, dans rust-http et la réponse de Chris Morgan est la méthode standard dans Rust actuel dans un avenir prévisible. Je ne suis pas sûr de savoir jusqu’où je peux vous emmener (et j’espère ne pas vous prendre la mauvaise direction!), Mais vous voudrez quelque chose comme:

 // Rust 0.6 -- old code /* extern mod std; use std::net_ip; use std::uv; fn main() { let iotask = uv::global_loop::get(); let result = net_ip::get_addr("www.duckduckgo.com", &iotask); io::println(fmt!("%?", result)); } */ 

En ce qui concerne l’encodage, il existe des exemples dans les tests unitaires de src / libstd / net_url.rs.

Utiliser des liaisons curl. Collez ceci dans votre Cargo.toml :

 [dependencies.curl] git = "https://github.com/carllerche/curl-rust" 

… et ceci dans le src/main.rs :

 extern crate curl; use curl::http; fn main(){ let resp = http::handle() .post("http://localhost:3000/login", "username=dude&password=sikrit") .exec().unwrap(); println!("code={}; headers={}; body={}", resp.get_code(), resp.get_headers(), resp.get_body()); }