web-dev-qa-db-fra.com

Comment faire une demande HTTP à partir de Rust?

Comment puis-je faire une demande HTTP à partir de Rust? Je n'arrive pas à trouver quoi que ce soit dans la bibliothèque principale.

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

Des bonus si quelqu'un peut me montrer comment encoder les paramètres de requête sur mon URL!

52
Alex Dean

Mise à jour: Cette réponse fait référence à une histoire assez ancienne. Pour les meilleures pratiques actuelles, veuillez consulter la réponse d'Isaac Aggrey à la place.


Je travaille sur Rust-http , qui est devenue la bibliothèque HTTP de facto pour Rust (Servo l'utilise); il est loin d'être complet et très mal documenté pour l'instant. Voici un exemple de demande et de faire quelque chose avec le code d'état:

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.

Rust-http suit la branche principale de Rust. À l'heure actuelle, cela fonctionnera dans le Rust 0.8), qui vient de sortir, mais il est probable qu'il y aura bientôt des changements.  En fait, aucune version de Rust-http ne fonctionne sur Rust 0.8 - il y a eu un changement de rupture qui ne peut pas être contourné dans les règles de confidentialité juste avant la sortie) , laissant quelque chose dont Rust-http dépend dans extra :: url inaccessible. Cela a depuis été corrigé, mais cela rend Rust-http incompatible avec Rust 0.8.


Quant à la question de l'encodage des chaînes de requête, cela devrait être fait actuellement avec extra::url::Query (un typedef pour ~[(~str, ~str)]). Fonctions appropriées pour les conversions:

22
Chris Morgan

La façon la plus simple de faire 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: Tokio boucle d'événements pour effectuer des requêtes non bloquantes et - futures-rs pour les futures/promesses. Un exemple basé sur Hyper est ci-dessous et est largement inspiré par n 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 d'origine ci-dessous, mais voir ci-dessus pour une mise à jour pour Rust 1.19 (dernière version stable à ce jour).

Je crois que ce que vous cherchez est dans la bibliothèque standard . maintenant dans Rust-http et la réponse de Chris Morgan est la manière standard dans le Rust pour l'avenir prévisible). Je ne sais pas jusqu'où je peux vous emmener (et j'espère que je ne vous emmène pas dans 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));
 }
 */

Quant au codage, il y a quelques exemples dans les tests unitaires dans src/libstd/net_url.rs.

47
Isaac Aggrey

Utilisation de fixations curl. Collez ceci dans votre Cargo.toml:

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

... et cela 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());    

}
15
dvdplm

Pour développer la réponse d'Isaac, voici un exemple de création de la requête POST avec les paramètres de requête à l'aide de la bibliothèque reqwest .

Cargo.toml

[package]
name = "play_async"
version = "0.1.0"
edition = "2018"

[dependencies]
reqwest = "0.9.14"
tokio = "0.1.18"
futures = "0.1.21"

Code

use futures::{Future, Stream};
use reqwest::r#async::{Client, Decoder};
use std::mem;

fn post_greeting() -> impl Future<Item=(), Error=()> {
    Client::new()
        .get("https://webhook.site/1dff66fd-07ff-4cb5-9a77-681efe863747")
        .header("Accepts", "application/json")
        .query(&[
            ("hello", "1"),
            ("world", "ABCD"),
        ])
        .send()
        .and_then(|mut res| {
            println!("{}", res.status());
            let body = mem::replace(res.body_mut(), Decoder::empty());
            body.concat2()
        })
        .map_err(|err| println!("request error: {}", err))
        .map(|body| {
            let v = body.to_vec();
            let s = String::from_utf8_lossy(&v);
            println!("response: {} ", s);
        })
}

fn main() {
    let f = post_greeting();
    tokio::run(f);
}

Allez-y https://webhook.site et créez votre lien webhook et changez de code. Vous verrez la demande reçue sur le serveur en temps réel.

Basé principalement sur l'exemple de Bastian Gruber ici https://github.com/gruberb/futures_playground

0
Patrik Stas