web-dev-qa-db-ja.com

RustからHTTPリクエストを行うにはどうすればよいですか?

RustからHTTPリクエストを作成するにはどうすればよいですか?コアライブラリには何も見つからないようです。

出力を解析する必要はありません。リクエストを行い、HTTPレスポンスコードを確認するだけです。

誰かがURLのクエリパラメータをURLエンコードする方法を教えてくれるとボーナスが得られます!

52
Alex Dean

更新:この回答はかなり古い歴史に関するものです。現在のベストプラクティスについては、代わりに Isaac Aggreyの答え をご覧ください。


私は Rust-http に取り組んできました。これはRust(Servoが使用する)のde factoHTTPライブラリになりました);それは完全とはほど遠いものであり、現在のところ非常に不十分に文書化されています。

_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);
    }
}
_

URLを唯一のコマンドライン引数としてこのコードを実行すると、ステータスコードがチェックされます! (HTTPのみ。HTTPSは使用できません。)

もう少し実行する例については、_src/examples/client/client.rs_と比較してください。

Rust-httpはRustのmasterブランチを追跡しています。 現在のところ、リリースされたばかりのRust 0.8で動作しますが、すぐに変更が破壊される可能性があります。 実際には、Rust-httpのバージョンはRust 0.8では動作しません。リリースの直前にプライバシールールで回避できない重大な変更がありました。 Rust-httpはextra :: url inaccessibleに依存しています。これは修正されていますが、Rust-httpはRust 0.8。と互換性がありません。


クエリ文字列のエンコードの問題については、現時点では _extra::url::Query_~[(~str, ~str)]のtypedef)で行う必要があります。変換に適切な関数:

22
Chris Morgan

Rust)でHTTPを実行する最も簡単な方法は reqwest です。これは Hyper 使いやすい。

Hyper は、Rustで人気のあるHTTPライブラリであり、2つのライブラリを利用します: Tokio )のイベントノンブロッキングリクエストを行うためのループおよび先物/約束のための futures-rsHyper ベースの例は以下であり、大部分は そのドキュメントの例に触発された

// 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();
}

Cargo.toml

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

後世のために、元の答えを以下に残しましたが、Rust 1.19(この記事の執筆時点での最新の安定版)の更新については上記を参照してください。

あなたが探しているのは 標準ライブラリ にあると思います。今 Rust-http で、Chris Morganの答えは、現在のRust予見可能な将来の標準的な方法です。 私はあなたをどこまで連れて行くことができるかわかりません(そして、私はあなたを間違った方向に連れて行かないことを望みます!)、しかしあなたは次のようなものが欲しいでしょう:

// 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));
 }
 */

エンコーディングについては、src/libstd/net_url.rsのユニットテストにいくつかの例があります。

47
Isaac Aggrey

Curlバインディングを使用します。これをCargo.toml

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

...そしてこれは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

Isaacの答えを詳しく説明するために、 reqwest ライブラリを使用してPOST=クエリパラメータを使用したリクエストを作成する例を示します。

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"

コード

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);
}

https://webhook.site に進み、webhookリンクを作成してコードを変更します。サーバーでリアルタイムに受信したリクエストが表示されます。

主にここのバスティアングルーバーの例に基づいています https://github.com/gruberb/futures_playground

0
Patrik Stas