How do I make an HTTP request from Rust?

2019-01-22 17:13发布

How can I make an HTTP request from Rust? I can't seem to find anything in the core library.

I don't need to parse the output, just make a request and check the HTTP response code.

Bonus marks if someone can show me how to URL encode the query parameters on my URL!

标签: http rust
3条回答
贪生不怕死
2楼-- · 2019-01-22 17:35

Update: This answer refers to fairly ancient history. For the current best practices, please look at Isaac Aggrey's answer instead.


I've been working on rust-http, which has become the de facto HTTP library for Rust (Servo uses it); it's far from complete and very poorly documented at present. Here's an example of making a request and doing something with the status 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);
    }
}

Run this code with a URL as the sole command-line argument and it'll check the status code! (HTTP only; no HTTPS.)

Compare with src/examples/client/client.rs for an example that does a little more.

rust-http is tracking the master branch of rust. At present it'll work in the just-released Rust 0.8, but there are likely to be breaking changes soon. Actually, no version of rust-http works on Rust 0.8—there was a breaking change which can't be worked around in privacy rules just before the release, leaving something that rust-http depends on in extra::url inaccessible. This has since been fixed, but it leaves rust-http incompatible with Rust 0.8.


As for the query string encoding matter, at present that should be done with extra::url::Query (a typedef for ~[(~str, ~str)]). Appropriate functions for conversions:

查看更多
beautiful°
3楼-- · 2019-01-22 17:58

The easiest way to do HTTP in Rust is reqwest. It is a wrapper to make Hyper easier to use.

Hyper is a popular HTTP library for Rust and utilizes two libraries: Tokio's event loop to make non-blocking requests and futures-rs for futures/promises. A Hyper-based example is below and is largely inspired by an example in its 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();
}

In Cargo.toml:

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

For posterity I've left my original answer below, but see above for an update for Rust 1.19 (latest stable version as of this writing).

I believe what you're looking for is in the standard library. now in rust-http and Chris Morgan's answer is the standard way in current Rust for the foreseeable future. I'm not sure how far I can take you (and hope I'm not taking you the wrong direction!), but you'll want something like:

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

As for encoding, there are some examples in the unit tests in src/libstd/net_url.rs.

查看更多
可以哭但决不认输i
4楼-- · 2019-01-22 18:01

Using curl bindings. Stick this in your Cargo.toml:

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

...and this in the 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());    

}
查看更多
登录 后发表回答