如何在Rust中进行GET请求?

26

我注意到Rust没有内置的库来处理HTTP,它只有一个处理原始IP和TCP协议的net模块。

我需要使用URL的&str,发送HTTP GET请求,如果成功则返回对应于HTML或JSON或其他响应的String&str字符串形式。

代码大致如下:

use somelib::http;

let response = http::get(&"http://stackoverflow.com");
match response {
    Some(suc) => suc,
    None => panic!
}

你尝试过在Google上搜索http crates吗?例如,这可能适合你 - user4815162342
2
这种问题在 Stack Overflow 上是不适合的,所以很可能会被关闭。如果到那时你还没有找到答案,我邀请你查看 Rust 标签 wiki 获取帮助 部分,其中详细介绍了其他开放式问题的场所。 - Matthieu M.
4个回答

19

目前在这个特定问题上的最佳实践是使用reqwest crate,如Rust Cookbook中所述。此代码略有改动以独立运行:

extern crate reqwest; // 0.9.18

use std::io::Read;

fn run() -> Result<(), Box<dyn std::error::Error>> {
    let mut res = reqwest::get("http://httpbin.org/get")?;
    let mut body = String::new();
    res.read_to_string(&mut body)?;

    println!("Status: {}", res.status());
    println!("Headers:\n{:#?}", res.headers());
    println!("Body:\n{}", body);

    Ok(())
}

正如食谱所述,此代码将同步执行。

另请参阅:


不幸的是,reqwest 需要 OpenSSL,因此如果您正在进行交叉编译,则不太好。 - Erik Berkun-Drevnig

15

看看Hyper

发送GET请求就这么简单。

let client = Client::new();

let res = client.get("http://example.domain").send().unwrap();
assert_eq!(res.status, hyper::Ok);

您可以在文档中找到更多示例。

编辑: 自从他们开始使用Tokio以来,Hyper变得有点复杂了。这里是更新版本。

extern crate futures;
extern crate hyper;
extern crate tokio_core;

use std::io::{self, Write};
use futures::{Future, Stream};
use hyper::Client;
use tokio_core::reactor::Core;


fn main() {
    let mut core = Core::new().unwrap();
    let client = Client::new(&core.handle());

    let uri = "http://httpbin.org/ip".parse().unwrap();
    let work =
        client.get(uri).and_then(|res| {
            println!("Response: {}", res.status());

            res.body().for_each(|chunk| {
                io::stdout()
                    .write_all(&chunk)
                    .map_err(From::from)
            })
        });
    core.run(work).unwrap();
}

这里是必要的依赖项。

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

11
由于 hyper::Client::new 现在需要一个句柄参数,因此原来的代码已经无法工作。 - marmistrz

6

建议使用Reqwest:

extern crate reqwest;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut res = reqwest::get("https://httpbin.org/headers")?;

    // copy the response body directly to stdout
    std::io::copy(&mut res, &mut std::io::stdout())?;

    Ok(())
}

一个回答建议reqwest已经存在。请非常清楚地说明这个新答案相对于现有答案提供了什么好处。 - Shepmaster
10
之前的答案无法编译,这个可以 :) - Luis San Martin
这就是为什么我们有能力对现有答案进行编辑的原因。它已经被编辑过了。 - Shepmaster
4
好的!但由于我是新用户,我不能对先前的回答进行评论或编辑。 - Luis San Martin
很遗憾,这个答案不再能编译。请更新或者删除它。 - jwh20

1
请注意,hyper 有很多依赖项,而 reqwest 不仅依赖于 hyper,还带来了相当多的额外依赖项。这可能对您来说是一个问题,也可能不是,但这是您应该知道的事情。
另一个您可能想考虑的选择是 minreq。默认情况下,该包只有一个依赖项(log 包),还有一些依赖于可选功能的其他依赖项。例如,如果您激活了 https-native 功能,它还会将 native-tls 添加为依赖项。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接