Rust - Reqwest examples
source link: https://dev.to/pintuch/rust-reqwest-examples-10ff
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Introduction
There are 3 things that need to happen:
- Building a client that can be reused across multiple requests
- Performing the execution of the network request
- Parsing the response
use std::collections::HashMap;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Build the client using the builder pattern
let client = reqwest::Client::builder()
.build()?;
// Perform the actual execution of the network request
let res = client
.get("https://httpbin.org/ip")
.send()
.await?;
// Parse the response body as Json in this case
let ip = res
.json::<HashMap<String, String>>()
.await?;
println!("{:?}", ip);
Ok(())
}
Instead of parsing the json body as a dynamic hash-map, you could use a well-defined struct
use serde::Deserialize;
#[derive(Deserialize, Debug)]
struct Ip {
origin: String
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Build the client using the builder pattern
let client = reqwest::Client::builder()
.build()?;
// Perform the actual execution of the network request
let res = client
.get("https://httpbin.org/ip")
.send()
.await?;
// Parse the response body as Json in this case
let ip = res
.json::<Ip>()
.await?;
println!("{:?}", ip);
Ok(())
}
Query Strings
let client = reqwest::Client::builder()
.build()?;
let res = client
.get("http://httpbin.org")
.query(&[("foo", "bar")])
.send()?;
POST JSON Data
The json(..)
method on the RequestBuilder
takes any value that can be serialized into JSON such as a HashMap or a Struct.
let mut map = HashMap::new();
map.insert("foo", "bar");
map.insert("buzz", "blah");
...
.json(&map)
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Serialize, Deserialize)]
struct Person {
first_name: String,
last_name: String,
}
#[derive(Debug, Serialize, Deserialize)]
struct PersonResponse {
data: String,
method: String,
headers: HashMap<String, String>
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let p = Person {
first_name: "Foo".into(),
last_name: "Bar".into(),
};
let res = reqwest::Client::new()
.post("https://httpbin.org/anything")
.json(&p)
.send()
.await?;
let js = res
.json::<PersonResponse>()
.await?;
let person: Person = serde_json::from_str(&js.data)?;
println!("{:#?}", person);
println!("Headers: {:#?}", js.headers);
Ok(())
}
POST Form data
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
struct Person {
first_name: String,
last_name: String,
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let p = Person {
first_name: "Foo".into(),
last_name: "Bar".into(),
};
let res = reqwest::Client::new()
.post("https://httpbin.org/anything")
.form(&p)
.send()
.await?;
let t = res
.text()
.await?;
println!("{}", t);
// $ cargo run
// Finished dev [unoptimized + debuginfo] target(s) in 0.09s
// Running `target/debug/reqwest-tut`
// {
// "args": {},
// "data": "",
// "files": {},
// "form": {
// "first_name": "Foo",
// "last_name": "Bar"
// },
// "headers": {
// "Accept": "*/*",
// "Content-Length": "28",
// "Content-Type": "application/x-www-form-urlencoded",
// "Host": "httpbin.org",
// "X-Amzn-Trace-Id": "Root=1-60453174-384d97870199933007fbb388"
// },
// "json": null,
// "method": "POST",
// "origin": "125.125.104.53",
// "url": "https://httpbin.org/anything"
// }
//
//
Ok(())
}
Request Headers
You can set the headers by calling the header(.., ..)
method on the request
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = reqwest::Client::builder()
.build()?;
let res = client
.post("https://httpbin.org/anything")
.body("arbitrary text")
.header("X-Person-First", "Foo!")
.header("X-Person-Last", "Bar!!")
.send()
.await?;
let t = res
.text()
.await?;
println!("{}", t);
// {
// "args": {},
// "data": "arbitrary text",
// "files": {},
// "form": {},
// "headers": {
// "Accept": "*/*",
// "Content-Length": "14",
// "Host": "httpbin.org",
// "X-Amzn-Trace-Id": "Root=1-604538df-218a5bb97264e7130c298b23",
// "X-Person-First": "Foo!",
// "X-Person-Last": "Bar!!"
// },
// "json": null,
// "method": "POST",
// "origin": "49.206.4.160",
// "url": "https://httpbin.org/anything"
// }
Ok(())
}
You can also set default headers on the client that can be overriden while making individual requests
use reqwest::header;
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
let mut headers = header::HeaderMap::new();
headers.insert("X-HEADER-1", header::HeaderValue::from_static("val1"));
headers.insert("X-HEADER-2", header::HeaderValue::from_static("val2"));
let client = reqwest::Client::builder()
.default_headers(headers)
.build()?;
let res = client
.get("https://httpbin.org/anything")
.body("whatever")
.header("X-HEADER-1", "overriden val1")
.send()
.await?;
println!("{}", res.text().await?);
// {
// "args": {},
// "data": "whatever",
// "files": {},
// "form": {},
// "headers": {
// "Accept": "*/*",
// "Content-Length": "8",
// "Host": "httpbin.org",
// "X-Amzn-Trace-Id": "Root=1-60453dad-429e59a434bd460b0a48e7d5",
// "X-Header-1": "overriden val1",
// "X-Header-2": "val2"
// },
// "json": null,
// "method": "GET",
// "origin": "49.206.4.160",
// "url": "https://httpbin.org/anything"
// }
Ok(())
}
Status Code
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
let client = reqwest::Client::builder().build()?;
let res = client
.get("https://httpbin.org/status/400")
.send()
.await?;
match res.status() {
reqwest::StatusCode::BAD_REQUEST => println!(
"content-length:{:?} server:{:?}",
res.headers().get(reqwest::header::CONTENT_LENGTH),
res.headers().get(reqwest::header::SERVER),
),
status => println!("status: {}", status),
}
// content-length:Some("0") server:Some("gunicorn/19.9.0")
Ok(())
}
Timeouts
Client Timeout
let client = reqwest::Client::builder()
.timeout(std::time::Duration::from_millis(500))
.build()?;
Connect Timeout
let client = reqwest::Client::builder()
.connect_timeout(std::time::Duration::from_millis(100))
.build()?;
Request Timeout
let res = client
.get(&url)
.timeout(std::time::Duration::from_millis(500))
.send()
.await;
Download data
use std::fs::File;
use std::io;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = reqwest::Client::builder().build()?;
let res = client
.get("https://httpbin.org/image/png")
.send()
.await?
.bytes()
.await?;
let mut data = res.as_ref();
let mut f = File::create("i.png")?;
io::copy(&mut data, &mut f)?;
Ok(())
}
// $ file i.png
// i.png: PNG image data, 100 x 100, 8-bit/color RGB, non-interlaced
Dependency configuration for the samples
[dependencies]
reqwest = { version = "0.11", features = ["json", "blocking", "cookies"] }
tokio = { version = "1", features = ["full"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1.0"
futures = "0.3"
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK