Make the async Client default (#626)
The previously default Client is moved to `reqwest::blocking`, while the async client becomes the main API. Closes #622
This commit is contained in:
22
README.md
22
README.md
@@ -20,13 +20,29 @@ preparing breaking changes, for most recently released code, look to the
|
||||
|
||||
## Example
|
||||
|
||||
```rust,no_run
|
||||
extern crate reqwest;
|
||||
Async:
|
||||
|
||||
```rust,no_run
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<std::error::Error>> {
|
||||
let resp: HashMap<String, String> = reqwest::get("https://httpbin.org/ip")
|
||||
.await?
|
||||
.json()
|
||||
.await?;
|
||||
println!("{:#?}", resp);
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
|
||||
Blocking:
|
||||
|
||||
```rust,no_run
|
||||
use std::collections::HashMap;
|
||||
|
||||
fn main() -> Result<(), Box<std::error::Error>> {
|
||||
let resp: HashMap<String, String> = reqwest::get("https://httpbin.org/ip")?
|
||||
let resp: HashMap<String, String> = reqwest::blocking::get("https://httpbin.org/ip")?
|
||||
.json()?;
|
||||
println!("{:#?}", resp);
|
||||
Ok(())
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
#![deny(warnings)]
|
||||
|
||||
use reqwest::r#async::Client;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), reqwest::Error> {
|
||||
let mut res = Client::new().get("https://hyper.rs").send().await?;
|
||||
|
||||
println!("Status: {}", res.status());
|
||||
|
||||
let body = res.text().await?;
|
||||
|
||||
println!("Body:\n\n{}", body);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
#![deny(warnings)]
|
||||
|
||||
use reqwest::r#async::{Client, Response};
|
||||
use serde::Deserialize;
|
||||
use std::future::Future;
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct Slideshow {
|
||||
title: String,
|
||||
author: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct SlideshowContainer {
|
||||
slideshow: Slideshow,
|
||||
}
|
||||
|
||||
async fn into_json<F>(f: F) -> Result<SlideshowContainer, reqwest::Error>
|
||||
where
|
||||
F: Future<Output = Result<Response, reqwest::Error>>,
|
||||
{
|
||||
let mut resp = f.await?;
|
||||
resp.json::<SlideshowContainer>().await
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), reqwest::Error> {
|
||||
let client = Client::new();
|
||||
|
||||
let request1 = client.get("https://httpbin.org/json").send();
|
||||
|
||||
let request2 = client.get("https://httpbin.org/json").send();
|
||||
|
||||
let (try_json1, try_json2) =
|
||||
futures::future::join(into_json(request1), into_json(request2)).await;
|
||||
|
||||
println!("{:?}", try_json1?);
|
||||
println!("{:?}", try_json2?);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
19
examples/blocking.rs
Normal file
19
examples/blocking.rs
Normal file
@@ -0,0 +1,19 @@
|
||||
//! `cargo run --example blocking`
|
||||
#![deny(warnings)]
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
env_logger::init();
|
||||
|
||||
println!("GET https://www.rust-lang.org");
|
||||
|
||||
let mut res = reqwest::blocking::get("https://www.rust-lang.org/")?;
|
||||
|
||||
println!("Status: {}", res.status());
|
||||
println!("Headers:\n{:?}", res.headers());
|
||||
|
||||
// copy the response body directly to stdout
|
||||
res.copy_to(&mut std::io::stdout())?;
|
||||
|
||||
println!("\n\nDone.");
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
fn main() {
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
reqwest::Client::new()
|
||||
.post("http://www.baidu.com")
|
||||
.form(&[("one", "1")])
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
//! really care about the structure of the JSON and just need to display it or
|
||||
//! process it at runtime.
|
||||
|
||||
fn main() -> Result<(), reqwest::Error> {
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), reqwest::Error> {
|
||||
let echo_json: serde_json::Value = reqwest::Client::new()
|
||||
.post("https://jsonplaceholder.typicode.com/posts")
|
||||
.json(&serde_json::json!({
|
||||
@@ -12,8 +13,10 @@ fn main() -> Result<(), reqwest::Error> {
|
||||
"body": "https://docs.rs/reqwest",
|
||||
"userId": 1
|
||||
}))
|
||||
.send()?
|
||||
.json()?;
|
||||
.send()
|
||||
.await?
|
||||
.json()
|
||||
.await?;
|
||||
|
||||
println!("{:#?}", echo_json);
|
||||
// Object(
|
||||
|
||||
@@ -15,7 +15,8 @@ struct Post {
|
||||
user_id: i32,
|
||||
}
|
||||
|
||||
fn main() -> Result<(), reqwest::Error> {
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), reqwest::Error> {
|
||||
let new_post = Post {
|
||||
id: None,
|
||||
title: "Reqwest.rs".into(),
|
||||
@@ -25,8 +26,10 @@ fn main() -> Result<(), reqwest::Error> {
|
||||
let new_post: Post = reqwest::Client::new()
|
||||
.post("https://jsonplaceholder.typicode.com/posts")
|
||||
.json(&new_post)
|
||||
.send()?
|
||||
.json()?;
|
||||
.send()
|
||||
.await?
|
||||
.json()
|
||||
.await?;
|
||||
|
||||
println!("{:#?}", new_post);
|
||||
// Post {
|
||||
|
||||
@@ -1,19 +1,17 @@
|
||||
//! `cargo run --example simple`
|
||||
#![deny(warnings)]
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
env_logger::init();
|
||||
|
||||
println!("GET https://www.rust-lang.org");
|
||||
|
||||
let mut res = reqwest::get("https://www.rust-lang.org/")?;
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), reqwest::Error> {
|
||||
let mut res = reqwest::Client::new()
|
||||
.get("https://hyper.rs")
|
||||
.send()
|
||||
.await?;
|
||||
|
||||
println!("Status: {}", res.status());
|
||||
println!("Headers:\n{:?}", res.headers());
|
||||
|
||||
// copy the response body directly to stdout
|
||||
res.copy_to(&mut std::io::stdout())?;
|
||||
let body = res.text().await?;
|
||||
|
||||
println!("Body:\n\n{}", body);
|
||||
|
||||
println!("\n\nDone.");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ impl Body {
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # use reqwest::r#async::Body;
|
||||
/// # use reqwest::Body;
|
||||
/// # use futures;
|
||||
/// # fn main() {
|
||||
/// let chunks: Vec<Result<_, ::std::io::Error>> = vec![
|
||||
|
||||
@@ -61,7 +61,7 @@ impl Form {
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let form = reqwest::r#async::multipart::Form::new()
|
||||
/// let form = reqwest::multipart::Form::new()
|
||||
/// .text("username", "seanmonstar")
|
||||
/// .text("password", "secret");
|
||||
/// ```
|
||||
|
||||
@@ -194,8 +194,8 @@ impl RequestBuilder {
|
||||
/// # use reqwest::Error;
|
||||
///
|
||||
/// # async fn run() -> Result<(), Error> {
|
||||
/// let client = reqwest::r#async::Client::new();
|
||||
/// let form = reqwest::r#async::multipart::Form::new()
|
||||
/// let client = reqwest::Client::new();
|
||||
/// let form = reqwest::multipart::Form::new()
|
||||
/// .text("key3", "value3")
|
||||
/// .text("key4", "value4");
|
||||
///
|
||||
@@ -329,7 +329,7 @@ impl RequestBuilder {
|
||||
/// # use reqwest::Error;
|
||||
/// #
|
||||
/// # async fn run() -> Result<(), Error> {
|
||||
/// let response = reqwest::r#async::Client::new()
|
||||
/// let response = reqwest::Client::new()
|
||||
/// .get("https://hyper.rs")
|
||||
/// .send()
|
||||
/// .await?;
|
||||
|
||||
@@ -186,7 +186,7 @@ impl Response {
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # use reqwest::r#async::Response;
|
||||
/// # use reqwest::Response;
|
||||
/// fn on_response(res: Response) {
|
||||
/// match res.error_for_status() {
|
||||
/// Ok(_res) => (),
|
||||
@@ -216,7 +216,7 @@ impl Response {
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # use reqwest::r#async::Response;
|
||||
/// # use reqwest::Response;
|
||||
/// fn on_response(res: &Response) {
|
||||
/// match res.error_for_status_ref() {
|
||||
/// Ok(_res) => (),
|
||||
@@ -347,25 +347,6 @@ struct ResponseUrl(Url);
|
||||
pub trait ResponseBuilderExt {
|
||||
/// A builder method for the `http::response::Builder` type that allows the user to add a `Url`
|
||||
/// to the `http::Response`
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # extern crate url;
|
||||
/// # extern crate http;
|
||||
/// # extern crate reqwest;
|
||||
/// # use std::error::Error;
|
||||
/// use url::Url;
|
||||
/// use http::response::Builder;
|
||||
/// use reqwest::r#async::ResponseBuilderExt;
|
||||
/// # fn main() -> Result<(), Box<dyn Error>> {
|
||||
/// let response = Builder::new()
|
||||
/// .status(200)
|
||||
/// .url(Url::parse("http://example.com")?)
|
||||
/// .body(())?;
|
||||
///
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
fn url(&mut self, url: Url) -> &mut Self;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ impl Body {
|
||||
///
|
||||
/// ```rust
|
||||
/// # use std::fs::File;
|
||||
/// # use reqwest::Body;
|
||||
/// # use reqwest::blocking::Body;
|
||||
/// # fn run() -> Result<(), Box<std::error::Error>> {
|
||||
/// let file = File::open("national_secrets.txt")?;
|
||||
/// let body = Body::new(file);
|
||||
@@ -45,7 +45,7 @@ impl Body {
|
||||
/// it can be reused.
|
||||
///
|
||||
/// ```rust
|
||||
/// # use reqwest::Body;
|
||||
/// # use reqwest::blocking::Body;
|
||||
/// # fn run() -> Result<(), Box<std::error::Error>> {
|
||||
/// let s = "A stringy body";
|
||||
/// let body = Body::from(s);
|
||||
@@ -64,7 +64,7 @@ impl Body {
|
||||
///
|
||||
/// ```rust
|
||||
/// # use std::fs::File;
|
||||
/// # use reqwest::Body;
|
||||
/// # use reqwest::blocking::Body;
|
||||
/// # fn run() -> Result<(), Box<std::error::Error>> {
|
||||
/// let file = File::open("a_large_file.txt")?;
|
||||
/// let file_size = file.metadata()?.len();
|
||||
@@ -10,9 +10,10 @@ use futures::{StreamExt, TryFutureExt};
|
||||
|
||||
use log::{error, trace};
|
||||
|
||||
use crate::request::{Request, RequestBuilder};
|
||||
use crate::response::Response;
|
||||
use crate::{async_impl, header, wait, IntoUrl, Method, Proxy, RedirectPolicy};
|
||||
use super::request::{Request, RequestBuilder};
|
||||
use super::response::Response;
|
||||
use super::wait;
|
||||
use crate::{async_impl, header, IntoUrl, Method, Proxy, RedirectPolicy};
|
||||
#[cfg(feature = "tls")]
|
||||
use crate::{Certificate, Identity};
|
||||
|
||||
@@ -28,9 +29,9 @@ use crate::{Certificate, Identity};
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # use reqwest::{Error, Client};
|
||||
/// use reqwest::blocking::Client;
|
||||
/// #
|
||||
/// # fn run() -> Result<(), Error> {
|
||||
/// # fn run() -> Result<(), reqwest::Error> {
|
||||
/// let client = Client::new();
|
||||
/// let resp = client.get("http://httpbin.org/").send()?;
|
||||
/// # drop(resp);
|
||||
@@ -51,7 +52,7 @@ pub struct Client {
|
||||
/// # fn run() -> Result<(), reqwest::Error> {
|
||||
/// use std::time::Duration;
|
||||
///
|
||||
/// let client = reqwest::Client::builder()
|
||||
/// let client = reqwest::blocking::Client::builder()
|
||||
/// .gzip(true)
|
||||
/// .timeout(Duration::from_secs(10))
|
||||
/// .build()?;
|
||||
@@ -130,7 +131,7 @@ impl ClientBuilder {
|
||||
/// let cert = reqwest::Certificate::from_der(&buf)?;
|
||||
///
|
||||
/// // get a client builder
|
||||
/// let client = reqwest::Client::builder()
|
||||
/// let client = reqwest::blocking::Client::builder()
|
||||
/// .add_root_certificate(cert)
|
||||
/// .build()?;
|
||||
/// # drop(client);
|
||||
@@ -170,7 +171,7 @@ impl ClientBuilder {
|
||||
/// let pkcs12 = reqwest::Identity::from_pem(&buf)?;
|
||||
///
|
||||
/// // get a client builder
|
||||
/// let client = reqwest::Client::builder()
|
||||
/// let client = reqwest::blocking::Client::builder()
|
||||
/// .identity(pkcs12)
|
||||
/// .build()?;
|
||||
/// # drop(client);
|
||||
@@ -224,7 +225,7 @@ impl ClientBuilder {
|
||||
/// headers.insert(header::AUTHORIZATION, header::HeaderValue::from_static("secret"));
|
||||
///
|
||||
/// // get a client builder
|
||||
/// let client = reqwest::Client::builder()
|
||||
/// let client = reqwest::blocking::Client::builder()
|
||||
/// .default_headers(headers)
|
||||
/// .build()?;
|
||||
/// let res = client.get("https://www.rust-lang.org").send()?;
|
||||
@@ -241,7 +242,7 @@ impl ClientBuilder {
|
||||
/// headers.insert(header::AUTHORIZATION, header::HeaderValue::from_static("secret"));
|
||||
///
|
||||
/// // get a client builder
|
||||
/// let client = reqwest::Client::builder()
|
||||
/// let client = reqwest::blocking::Client::builder()
|
||||
/// .default_headers(headers)
|
||||
/// .build()?;
|
||||
/// let res = client
|
||||
@@ -337,7 +338,7 @@ impl ClientBuilder {
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// let client = reqwest::Client::builder()
|
||||
/// let client = reqwest::blocking::Client::builder()
|
||||
/// .h2_prior_knowledge()
|
||||
/// .build().unwrap();
|
||||
/// ```
|
||||
@@ -350,7 +351,7 @@ impl ClientBuilder {
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// let client = reqwest::Client::builder()
|
||||
/// let client = reqwest::blocking::Client::builder()
|
||||
/// .http1_title_case_headers()
|
||||
/// .build().unwrap();
|
||||
/// ```
|
||||
@@ -365,7 +366,7 @@ impl ClientBuilder {
|
||||
/// ```
|
||||
/// use std::net::IpAddr;
|
||||
/// let local_addr = IpAddr::from([12, 4, 1, 8]);
|
||||
/// let client = reqwest::Client::builder()
|
||||
/// let client = reqwest::blocking::Client::builder()
|
||||
/// .local_address(local_addr)
|
||||
/// .build().unwrap();
|
||||
/// ```
|
||||
@@ -386,7 +387,7 @@ impl ClientBuilder {
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// let client = reqwest::Client::builder()
|
||||
/// let client = reqwest::blocking::Client::builder()
|
||||
/// .cookie_store(true)
|
||||
/// .build()
|
||||
/// .unwrap();
|
||||
98
src/blocking/mod.rs
Normal file
98
src/blocking/mod.rs
Normal file
@@ -0,0 +1,98 @@
|
||||
//! A blocking Client API.
|
||||
//!
|
||||
//! The blocking `Client` will block the current thread to execute, instead
|
||||
//! of returning futures that need to be executed on a runtime.
|
||||
//!
|
||||
//! ## Making a GET request
|
||||
//!
|
||||
//! For a single request, you can use the [`get`](get) shortcut method.
|
||||
//!
|
||||
//! ```rust
|
||||
//! # use reqwest::{Error, Response};
|
||||
//!
|
||||
//! # fn run() -> Result<(), Error> {
|
||||
//! let body = reqwest::blocking::get("https://www.rust-lang.org")?
|
||||
//! .text()?;
|
||||
//!
|
||||
//! println!("body = {:?}", body);
|
||||
//! # Ok(())
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! Additionally, the blocking [`Response`](Response) struct implements Rust's
|
||||
//! `Read` trait, so many useful standard library and third party crates will
|
||||
//! have convenience methods that take a `Response` anywhere `T: Read` is
|
||||
//! acceptable.
|
||||
//!
|
||||
//! **NOTE**: If you plan to perform multiple requests, it is best to create a
|
||||
//! [`Client`](Client) and reuse it, taking advantage of keep-alive connection
|
||||
//! pooling.
|
||||
//!
|
||||
//! ## Making POST requests (or setting request bodies)
|
||||
//!
|
||||
//! There are several ways you can set the body of a request. The basic one is
|
||||
//! by using the `body()` method of a [`RequestBuilder`](RequestBuilder). This lets you set the
|
||||
//! exact raw bytes of what the body should be. It accepts various types,
|
||||
//! including `String`, `Vec<u8>`, and `File`. If you wish to pass a custom
|
||||
//! Reader, you can use the `reqwest::blocking::Body::new()` constructor.
|
||||
//!
|
||||
//! ```rust
|
||||
//! # use reqwest::Error;
|
||||
//! #
|
||||
//! # fn run() -> Result<(), Error> {
|
||||
//! let client = reqwest::blocking::Client::new();
|
||||
//! let res = client.post("http://httpbin.org/post")
|
||||
//! .body("the exact body that is sent")
|
||||
//! .send()?;
|
||||
//! # Ok(())
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! ## And More
|
||||
//!
|
||||
//! Most features available to the asynchronous `Client` are also available,
|
||||
//! on the blocking `Client`, see those docs for more.
|
||||
|
||||
mod body;
|
||||
mod client;
|
||||
pub mod multipart;
|
||||
mod request;
|
||||
mod response;
|
||||
mod wait;
|
||||
|
||||
pub(crate) use self::wait::Waited;
|
||||
|
||||
pub use self::body::Body;
|
||||
pub use self::client::{Client, ClientBuilder};
|
||||
pub use self::request::{Request, RequestBuilder};
|
||||
pub use self::response::Response;
|
||||
|
||||
/// Shortcut method to quickly make a *blocking* `GET` request.
|
||||
///
|
||||
/// **NOTE**: This function creates a new internal `Client` on each call,
|
||||
/// and so should not be used if making many requests. Create a
|
||||
/// [`Client`](./struct.Client.html) instead.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # fn run() -> Result<(), reqwest::Error> {
|
||||
/// let body = reqwest::blocking::get("https://www.rust-lang.org")?
|
||||
/// .text()?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// # fn main() { }
|
||||
/// ```
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This function fails if:
|
||||
///
|
||||
/// - native TLS backend cannot be initialized
|
||||
/// - supplied `Url` cannot be parsed
|
||||
/// - there was an error while sending request
|
||||
/// - redirect loop was detected
|
||||
/// - redirect limit was exhausted
|
||||
pub fn get<T: crate::IntoUrl>(url: T) -> crate::Result<Response> {
|
||||
Client::builder().build()?.get(url).send()
|
||||
}
|
||||
@@ -7,7 +7,7 @@
|
||||
//! # Example
|
||||
//!
|
||||
//! ```
|
||||
//! use reqwest::multipart;
|
||||
//! use reqwest::blocking::multipart;
|
||||
//!
|
||||
//! # fn run() -> Result<(), Box<dyn std::error::Error>> {
|
||||
//! let form = multipart::Form::new()
|
||||
@@ -25,7 +25,7 @@
|
||||
//! let form = form.part("biography", bio);
|
||||
//!
|
||||
//! // And finally, send the form
|
||||
//! let client = reqwest::Client::new();
|
||||
//! let client = reqwest::blocking::Client::new();
|
||||
//! let resp = client
|
||||
//! .post("http://localhost:8080/user")
|
||||
//! .multipart(form)
|
||||
@@ -44,8 +44,8 @@ use std::path::Path;
|
||||
|
||||
use mime_guess::{self, Mime};
|
||||
|
||||
use super::Body;
|
||||
use crate::async_impl::multipart::{FormParts, PartMetadata, PartProps};
|
||||
use crate::Body;
|
||||
|
||||
/// A multipart/form-data request.
|
||||
pub struct Form {
|
||||
@@ -77,7 +77,7 @@ impl Form {
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let form = reqwest::multipart::Form::new()
|
||||
/// let form = reqwest::blocking::multipart::Form::new()
|
||||
/// .text("username", "seanmonstar")
|
||||
/// .text("password", "secret");
|
||||
/// ```
|
||||
@@ -97,7 +97,7 @@ impl Form {
|
||||
///
|
||||
/// ```no_run
|
||||
/// # fn run() -> std::io::Result<()> {
|
||||
/// let files = reqwest::multipart::Form::new()
|
||||
/// let files = reqwest::blocking::multipart::Form::new()
|
||||
/// .file("key", "/path/to/file")?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
@@ -1,14 +1,16 @@
|
||||
use std::fmt;
|
||||
|
||||
use base64::encode;
|
||||
use http::HttpTryFrom;
|
||||
use serde::Serialize;
|
||||
use serde_json;
|
||||
use serde_urlencoded;
|
||||
|
||||
use crate::body::{self, Body};
|
||||
use super::body::{self, Body};
|
||||
use super::multipart;
|
||||
use super::Client;
|
||||
use crate::header::{HeaderMap, HeaderName, HeaderValue, CONTENT_TYPE};
|
||||
use crate::{async_impl, Client, Method, Url};
|
||||
use http::HttpTryFrom;
|
||||
use crate::{async_impl, Method, Url};
|
||||
|
||||
/// A request which can be executed with `Client::execute()`.
|
||||
pub struct Request {
|
||||
@@ -128,7 +130,7 @@ impl RequestBuilder {
|
||||
/// use reqwest::header::USER_AGENT;
|
||||
///
|
||||
/// # fn run() -> Result<(), Box<std::error::Error>> {
|
||||
/// let client = reqwest::Client::new();
|
||||
/// let client = reqwest::blocking::Client::new();
|
||||
/// let res = client.get("https://www.rust-lang.org")
|
||||
/// .header(USER_AGENT, "foo")
|
||||
/// .send()?;
|
||||
@@ -175,7 +177,7 @@ impl RequestBuilder {
|
||||
///
|
||||
/// # fn run() -> Result<(), Box<std::error::Error>> {
|
||||
/// let file = fs::File::open("much_beauty.png")?;
|
||||
/// let client = reqwest::Client::new();
|
||||
/// let client = reqwest::blocking::Client::new();
|
||||
/// let res = client.post("http://httpbin.org/post")
|
||||
/// .headers(construct_headers())
|
||||
/// .body(file)
|
||||
@@ -190,36 +192,11 @@ impl RequestBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
/// Set a header with a type implementing hyper v0.11's `Header` trait.
|
||||
///
|
||||
/// This method is provided to ease migration, and requires the `hyper-011`
|
||||
/// Cargo feature enabled on `reqwest`.
|
||||
#[cfg(feature = "hyper-011")]
|
||||
pub fn header_011<H>(self, header: H) -> RequestBuilder
|
||||
where
|
||||
H: crate::hyper_011::header::Header,
|
||||
{
|
||||
let mut headers = crate::hyper_011::Headers::new();
|
||||
headers.set(header);
|
||||
let map = crate::header::HeaderMap::from(headers);
|
||||
self.headers(map)
|
||||
}
|
||||
|
||||
/// Set multiple headers using hyper v0.11's `Headers` map.
|
||||
///
|
||||
/// This method is provided to ease migration, and requires the `hyper-011`
|
||||
/// Cargo feature enabled on `reqwest`.
|
||||
#[cfg(feature = "hyper-011")]
|
||||
pub fn headers_011(self, headers: crate::hyper_011::Headers) -> RequestBuilder {
|
||||
let map = crate::header::HeaderMap::from(headers);
|
||||
self.headers(map)
|
||||
}
|
||||
|
||||
/// Enable HTTP basic authentication.
|
||||
///
|
||||
/// ```rust
|
||||
/// # fn run() -> Result<(), Box<std::error::Error>> {
|
||||
/// let client = reqwest::Client::new();
|
||||
/// let client = reqwest::blocking::Client::new();
|
||||
/// let resp = client.delete("http://httpbin.org/delete")
|
||||
/// .basic_auth("admin", Some("good password"))
|
||||
/// .send()?;
|
||||
@@ -243,7 +220,7 @@ impl RequestBuilder {
|
||||
///
|
||||
/// ```rust
|
||||
/// # fn run() -> Result<(), Box<std::error::Error>> {
|
||||
/// let client = reqwest::Client::new();
|
||||
/// let client = reqwest::blocking::Client::new();
|
||||
/// let resp = client.delete("http://httpbin.org/delete")
|
||||
/// .bearer_auth("token")
|
||||
/// .send()?;
|
||||
@@ -266,7 +243,7 @@ impl RequestBuilder {
|
||||
///
|
||||
/// ```rust
|
||||
/// # fn run() -> Result<(), Box<std::error::Error>> {
|
||||
/// let client = reqwest::Client::new();
|
||||
/// let client = reqwest::blocking::Client::new();
|
||||
/// let res = client.post("http://httpbin.org/post")
|
||||
/// .body("from a &str!")
|
||||
/// .send()?;
|
||||
@@ -277,10 +254,9 @@ impl RequestBuilder {
|
||||
/// Using a `File`:
|
||||
///
|
||||
/// ```rust
|
||||
/// # use std::fs;
|
||||
/// # fn run() -> Result<(), Box<std::error::Error>> {
|
||||
/// let file = fs::File::open("from_a_file.txt")?;
|
||||
/// let client = reqwest::Client::new();
|
||||
/// let file = std::fs::File::open("from_a_file.txt")?;
|
||||
/// let client = reqwest::blocking::Client::new();
|
||||
/// let res = client.post("http://httpbin.org/post")
|
||||
/// .body(file)
|
||||
/// .send()?;
|
||||
@@ -295,7 +271,7 @@ impl RequestBuilder {
|
||||
/// # fn run() -> Result<(), Box<std::error::Error>> {
|
||||
/// // from bytes!
|
||||
/// let bytes: Vec<u8> = vec![1, 10, 100];
|
||||
/// let client = reqwest::Client::new();
|
||||
/// let client = reqwest::blocking::Client::new();
|
||||
/// let res = client.post("http://httpbin.org/post")
|
||||
/// .body(bytes)
|
||||
/// .send()?;
|
||||
@@ -322,7 +298,7 @@ impl RequestBuilder {
|
||||
/// # use reqwest::Error;
|
||||
/// #
|
||||
/// # fn run() -> Result<(), Error> {
|
||||
/// let client = reqwest::Client::new();
|
||||
/// let client = reqwest::blocking::Client::new();
|
||||
/// let res = client.get("http://httpbin.org")
|
||||
/// .query(&[("lang", "rust")])
|
||||
/// .send()?;
|
||||
@@ -375,7 +351,7 @@ impl RequestBuilder {
|
||||
/// let mut params = HashMap::new();
|
||||
/// params.insert("lang", "rust");
|
||||
///
|
||||
/// let client = reqwest::Client::new();
|
||||
/// let client = reqwest::blocking::Client::new();
|
||||
/// let res = client.post("http://httpbin.org")
|
||||
/// .form(¶ms)
|
||||
/// .send()?;
|
||||
@@ -420,7 +396,7 @@ impl RequestBuilder {
|
||||
/// let mut map = HashMap::new();
|
||||
/// map.insert("lang", "rust");
|
||||
///
|
||||
/// let client = reqwest::Client::new();
|
||||
/// let client = reqwest::blocking::Client::new();
|
||||
/// let res = client.post("http://httpbin.org")
|
||||
/// .json(&map)
|
||||
/// .send()?;
|
||||
@@ -456,8 +432,8 @@ impl RequestBuilder {
|
||||
/// # use reqwest::Error;
|
||||
///
|
||||
/// # fn run() -> Result<(), Box<std::error::Error>> {
|
||||
/// let client = reqwest::Client::new();
|
||||
/// let form = reqwest::multipart::Form::new()
|
||||
/// let client = reqwest::blocking::Client::new();
|
||||
/// let form = reqwest::blocking::multipart::Form::new()
|
||||
/// .text("key3", "value3")
|
||||
/// .file("file", "/path/to/field")?;
|
||||
///
|
||||
@@ -469,7 +445,7 @@ impl RequestBuilder {
|
||||
/// ```
|
||||
///
|
||||
/// See [`multipart`](multipart/) for more examples.
|
||||
pub fn multipart(self, mut multipart: crate::multipart::Form) -> RequestBuilder {
|
||||
pub fn multipart(self, mut multipart: multipart::Form) -> RequestBuilder {
|
||||
let mut builder = self.header(
|
||||
CONTENT_TYPE,
|
||||
format!("multipart/form-data; boundary={}", multipart.boundary()).as_str(),
|
||||
@@ -495,7 +471,7 @@ impl RequestBuilder {
|
||||
///
|
||||
/// This method fails if there was an error while sending request,
|
||||
/// redirect loop was detected or redirect limit was exhausted.
|
||||
pub fn send(self) -> crate::Result<crate::Response> {
|
||||
pub fn send(self) -> crate::Result<super::Response> {
|
||||
self.client.execute(self.request?)
|
||||
}
|
||||
|
||||
@@ -510,7 +486,7 @@ impl RequestBuilder {
|
||||
///
|
||||
/// ```rust
|
||||
/// # fn run() -> Result<(), Box<std::error::Error>> {
|
||||
/// let client = reqwest::Client::new();
|
||||
/// let client = reqwest::blocking::Client::new();
|
||||
/// let builder = client.post("http://httpbin.org/post")
|
||||
/// .body("from a &str!");
|
||||
/// let clone = builder.try_clone();
|
||||
@@ -523,7 +499,7 @@ impl RequestBuilder {
|
||||
///
|
||||
/// ```rust
|
||||
/// # fn run() -> Result<(), Box<std::error::Error>> {
|
||||
/// let client = reqwest::Client::new();
|
||||
/// let client = reqwest::blocking::Client::new();
|
||||
/// let builder = client.get("http://httpbin.org/get");
|
||||
/// let clone = builder.try_clone();
|
||||
/// assert!(clone.is_some());
|
||||
@@ -535,9 +511,9 @@ impl RequestBuilder {
|
||||
///
|
||||
/// ```rust
|
||||
/// # fn run() -> Result<(), Box<std::error::Error>> {
|
||||
/// let client = reqwest::Client::new();
|
||||
/// let client = reqwest::blocking::Client::new();
|
||||
/// let builder = client.get("http://httpbin.org/get")
|
||||
/// .body(reqwest::Body::new(std::io::empty()));
|
||||
/// .body(reqwest::blocking::Body::new(std::io::empty()));
|
||||
/// let clone = builder.try_clone();
|
||||
/// assert!(clone.is_none());
|
||||
/// # Ok(())
|
||||
@@ -572,8 +548,9 @@ fn fmt_request_fields<'a, 'b>(
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::super::{body, Client};
|
||||
use crate::header::{HeaderMap, HeaderValue, ACCEPT, CONTENT_TYPE, HOST};
|
||||
use crate::{body, Client, Method};
|
||||
use crate::Method;
|
||||
use serde::Serialize;
|
||||
use serde_json;
|
||||
use serde_urlencoded;
|
||||
@@ -6,12 +6,13 @@ use std::pin::Pin;
|
||||
use std::time::Duration;
|
||||
|
||||
use http;
|
||||
use hyper::header::HeaderMap;
|
||||
use serde::de::DeserializeOwned;
|
||||
|
||||
use crate::client::KeepCoreThreadAlive;
|
||||
use super::client::KeepCoreThreadAlive;
|
||||
use super::wait;
|
||||
use crate::cookie;
|
||||
use crate::{async_impl, wait, StatusCode, Url, Version};
|
||||
use hyper::header::HeaderMap;
|
||||
use crate::{async_impl, StatusCode, Url, Version};
|
||||
|
||||
/// A Response to a submitted `Request`.
|
||||
pub struct Response {
|
||||
@@ -49,7 +50,7 @@ impl Response {
|
||||
///
|
||||
/// ```rust
|
||||
/// # fn run() -> Result<(), Box<std::error::Error>> {
|
||||
/// let resp = reqwest::get("http://httpbin.org/get")?;
|
||||
/// let resp = reqwest::blocking::get("http://httpbin.org/get")?;
|
||||
/// if resp.status().is_success() {
|
||||
/// println!("success!");
|
||||
/// } else if resp.status().is_server_error() {
|
||||
@@ -64,7 +65,7 @@ impl Response {
|
||||
/// Checking for specific status codes:
|
||||
///
|
||||
/// ```rust
|
||||
/// use reqwest::Client;
|
||||
/// use reqwest::blocking::Client;
|
||||
/// use reqwest::StatusCode;
|
||||
/// # fn run() -> Result<(), Box<std::error::Error>> {
|
||||
/// let client = Client::new();
|
||||
@@ -95,7 +96,7 @@ impl Response {
|
||||
/// Saving an etag when caching a file:
|
||||
///
|
||||
/// ```
|
||||
/// use reqwest::Client;
|
||||
/// use reqwest::blocking::Client;
|
||||
/// use reqwest::header::ETAG;
|
||||
///
|
||||
/// # fn run() -> Result<(), Box<std::error::Error>> {
|
||||
@@ -136,7 +137,7 @@ impl Response {
|
||||
///
|
||||
/// ```rust
|
||||
/// # fn run() -> Result<(), Box<std::error::Error>> {
|
||||
/// let resp = reqwest::get("http://httpbin.org/redirect/1")?;
|
||||
/// let resp = reqwest::blocking::get("http://httpbin.org/redirect/1")?;
|
||||
/// assert_eq!(resp.url().as_str(), "http://httpbin.org/get");
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
@@ -152,7 +153,7 @@ impl Response {
|
||||
///
|
||||
/// ```rust
|
||||
/// # fn run() -> Result<(), Box<std::error::Error>> {
|
||||
/// let resp = reqwest::get("http://httpbin.org/redirect/1")?;
|
||||
/// let resp = reqwest::blocking::get("http://httpbin.org/redirect/1")?;
|
||||
/// println!("httpbin.org address: {:?}", resp.remote_addr());
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
@@ -189,7 +190,7 @@ impl Response {
|
||||
/// }
|
||||
///
|
||||
/// # fn run() -> Result<(), Error> {
|
||||
/// let json: Ip = reqwest::get("http://httpbin.org/ip")?.json()?;
|
||||
/// let json: Ip = reqwest::blocking::get("http://httpbin.org/ip")?.json()?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// #
|
||||
@@ -223,7 +224,7 @@ impl Response {
|
||||
/// ```rust
|
||||
/// # extern crate reqwest;
|
||||
/// # fn run() -> Result<(), Box<std::error::Error>> {
|
||||
/// let content = reqwest::get("http://httpbin.org/range/26")?.text()?;
|
||||
/// let content = reqwest::blocking::get("http://httpbin.org/range/26")?.text()?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
@@ -250,7 +251,8 @@ impl Response {
|
||||
/// ```rust
|
||||
/// # extern crate reqwest;
|
||||
/// # fn run() -> Result<(), Box<std::error::Error>> {
|
||||
/// let content = reqwest::get("http://httpbin.org/range/26")?.text_with_charset("utf-8")?;
|
||||
/// let content = reqwest::blocking::get("http://httpbin.org/range/26")?
|
||||
/// .text_with_charset("utf-8")?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
@@ -282,7 +284,7 @@ impl Response {
|
||||
///
|
||||
/// ```rust
|
||||
/// # fn run() -> Result<(), Box<std::error::Error>> {
|
||||
/// let mut resp = reqwest::get("http://httpbin.org/range/5")?;
|
||||
/// let mut resp = reqwest::blocking::get("http://httpbin.org/range/5")?;
|
||||
/// let mut buf: Vec<u8> = vec![];
|
||||
/// resp.copy_to(&mut buf)?;
|
||||
/// assert_eq!(b"abcde", buf.as_slice());
|
||||
@@ -303,7 +305,7 @@ impl Response {
|
||||
/// ```rust,no_run
|
||||
/// # extern crate reqwest;
|
||||
/// # fn run() -> Result<(), Box<std::error::Error>> {
|
||||
/// let res = reqwest::get("http://httpbin.org/status/400")?
|
||||
/// let res = reqwest::blocking::get("http://httpbin.org/status/400")?
|
||||
/// .error_for_status();
|
||||
/// if let Err(err) = res {
|
||||
/// assert_eq!(err.status(), Some(reqwest::StatusCode::BAD_REQUEST));
|
||||
@@ -312,7 +314,6 @@ impl Response {
|
||||
/// # }
|
||||
/// # fn main() {}
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn error_for_status(self) -> crate::Result<Self> {
|
||||
let Response {
|
||||
body,
|
||||
@@ -335,7 +336,7 @@ impl Response {
|
||||
/// ```rust,no_run
|
||||
/// # extern crate reqwest;
|
||||
/// # fn run() -> Result<(), Box<std::error::Error>> {
|
||||
/// let res = reqwest::get("http://httpbin.org/status/400")?;
|
||||
/// let res = reqwest::blocking::get("http://httpbin.org/status/400")?;
|
||||
/// let res = res.error_for_status_ref();
|
||||
/// if let Err(err) = res {
|
||||
/// assert_eq!(err.status(), Some(reqwest::StatusCode::BAD_REQUEST));
|
||||
@@ -344,7 +345,6 @@ impl Response {
|
||||
/// # }
|
||||
/// # fn main() {}
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn error_for_status_ref(&self) -> crate::Result<&Self> {
|
||||
self.inner.error_for_status_ref().and_then(|_| Ok(self))
|
||||
}
|
||||
35
src/error.rs
35
src/error.rs
@@ -20,15 +20,15 @@ use crate::{StatusCode, Url};
|
||||
/// }
|
||||
/// # fn main() { }
|
||||
///
|
||||
/// fn run() {
|
||||
/// match make_request() {
|
||||
/// async fn run() {
|
||||
/// match make_request().await {
|
||||
/// Err(e) => handler(e),
|
||||
/// Ok(_) => return,
|
||||
/// }
|
||||
/// }
|
||||
/// // Response is not a json object conforming to the Simple struct
|
||||
/// fn make_request() -> Result<Simple, reqwest::Error> {
|
||||
/// reqwest::get("http://httpbin.org/ip")?.json()
|
||||
/// async fn make_request() -> Result<Simple, reqwest::Error> {
|
||||
/// reqwest::get("http://httpbin.org/ip").await?.json().await
|
||||
/// }
|
||||
///
|
||||
/// fn handler(e: reqwest::Error) {
|
||||
@@ -75,9 +75,9 @@ impl Error {
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # fn run() {
|
||||
/// # async fn run() {
|
||||
/// // displays last stop of a redirect loop
|
||||
/// let response = reqwest::get("http://site.with.redirect.loop");
|
||||
/// let response = reqwest::get("http://site.with.redirect.loop").await;
|
||||
/// if let Err(e) = response {
|
||||
/// if e.is_redirect() {
|
||||
/// if let Some(final_stop) = e.url() {
|
||||
@@ -108,14 +108,14 @@ impl Error {
|
||||
/// extern crate url;
|
||||
/// # extern crate reqwest;
|
||||
/// // retries requests with no host on localhost
|
||||
/// # fn run() {
|
||||
/// # async fn run() {
|
||||
/// let invalid_request = "http://";
|
||||
/// let mut response = reqwest::get(invalid_request);
|
||||
/// let mut response = reqwest::get(invalid_request).await;
|
||||
/// if let Err(e) = response {
|
||||
/// match e.get_ref().and_then(|e| e.downcast_ref::<url::ParseError>()) {
|
||||
/// Some(&url::ParseError::EmptyHost) => {
|
||||
/// let valid_request = format!("{}{}",invalid_request, "localhost");
|
||||
/// response = reqwest::get(&valid_request);
|
||||
/// response = reqwest::get(&valid_request).await;
|
||||
/// },
|
||||
/// _ => (),
|
||||
/// }
|
||||
@@ -123,7 +123,6 @@ impl Error {
|
||||
/// # }
|
||||
/// # fn main() {}
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn get_ref(&self) -> Option<&(dyn StdError + Send + Sync + 'static)> {
|
||||
match self.inner.kind {
|
||||
Kind::Http(ref e) => Some(e),
|
||||
@@ -152,7 +151,6 @@ impl Error {
|
||||
}
|
||||
|
||||
/// Returns true if the error is related to HTTP.
|
||||
#[inline]
|
||||
pub fn is_http(&self) -> bool {
|
||||
match self.inner.kind {
|
||||
Kind::Http(_) => true,
|
||||
@@ -175,7 +173,6 @@ impl Error {
|
||||
}
|
||||
|
||||
/// Returns true if the error is serialization related.
|
||||
#[inline]
|
||||
pub fn is_serialization(&self) -> bool {
|
||||
match self.inner.kind {
|
||||
Kind::Json(_) | Kind::UrlEncoded(_) => true,
|
||||
@@ -184,7 +181,6 @@ impl Error {
|
||||
}
|
||||
|
||||
/// Returns true if the error is from a `RedirectPolicy`.
|
||||
#[inline]
|
||||
pub fn is_redirect(&self) -> bool {
|
||||
match self.inner.kind {
|
||||
Kind::TooManyRedirects | Kind::RedirectLoop => true,
|
||||
@@ -193,7 +189,6 @@ impl Error {
|
||||
}
|
||||
|
||||
/// Returns true if the error is from a request returning a 4xx error.
|
||||
#[inline]
|
||||
pub fn is_client_error(&self) -> bool {
|
||||
match self.inner.kind {
|
||||
Kind::Status(code) => code.is_client_error(),
|
||||
@@ -202,7 +197,6 @@ impl Error {
|
||||
}
|
||||
|
||||
/// Returns true if the error is from a request returning a 5xx error.
|
||||
#[inline]
|
||||
pub fn is_server_error(&self) -> bool {
|
||||
match self.inner.kind {
|
||||
Kind::Status(code) => code.is_server_error(),
|
||||
@@ -211,7 +205,6 @@ impl Error {
|
||||
}
|
||||
|
||||
/// Returns the status code, if the error was generated from a response.
|
||||
#[inline]
|
||||
pub fn status(&self) -> Option<StatusCode> {
|
||||
match self.inner.kind {
|
||||
Kind::Status(code) => Some(code),
|
||||
@@ -466,15 +459,15 @@ impl From<rustls::TLSError> for Kind {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<crate::wait::Waited<T>> for Kind
|
||||
impl<T> From<crate::blocking::Waited<T>> for Kind
|
||||
where
|
||||
T: Into<Kind>,
|
||||
{
|
||||
fn from(err: crate::wait::Waited<T>) -> Kind {
|
||||
fn from(err: crate::blocking::Waited<T>) -> Kind {
|
||||
match err {
|
||||
crate::wait::Waited::TimedOut => io_timeout().into(),
|
||||
crate::wait::Waited::Executor(e) => e.into(),
|
||||
crate::wait::Waited::Inner(e) => e.into(),
|
||||
crate::blocking::Waited::TimedOut => io_timeout().into(),
|
||||
crate::blocking::Waited::Executor(e) => e.into(),
|
||||
crate::blocking::Waited::Inner(e) => e.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
78
src/lib.rs
78
src/lib.rs
@@ -11,15 +11,16 @@
|
||||
//! It handles many of the things that most people just expect an HTTP client
|
||||
//! to do for them.
|
||||
//!
|
||||
//! - Async and [blocking](blocking) Clients
|
||||
//! - Plain bodies, [JSON](#json), [urlencoded](#forms), [multipart](multipart)
|
||||
//! - Customizable [redirect policy](#redirect-policy)
|
||||
//! - HTTP [Proxies](#proxies)
|
||||
//! - Uses system-native [TLS](#tls)
|
||||
//! - Cookies
|
||||
//!
|
||||
//! The [`reqwest::Client`][client] is synchronous, making it a great fit for
|
||||
//! applications that only require a few HTTP requests, and wish to handle
|
||||
//! them synchronously.
|
||||
//! The [`reqwest::Client`][client] is asynchronous. For applications wishing
|
||||
//! to only make a few HTTP requests, the [`reqwest::blocking`](blocking) API
|
||||
//! may be more convenient.
|
||||
//!
|
||||
//! Additional learning resources include:
|
||||
//!
|
||||
@@ -31,22 +32,17 @@
|
||||
//! For a single request, you can use the [`get`][get] shortcut method.
|
||||
//!
|
||||
//! ```rust
|
||||
//! # use reqwest::{Error, Response};
|
||||
//!
|
||||
//! # fn run() -> Result<(), Error> {
|
||||
//! let body = reqwest::get("https://www.rust-lang.org")?
|
||||
//! .text()?;
|
||||
//! # async fn run() -> Result<(), reqwest::Error> {
|
||||
//! let body = reqwest::get("https://www.rust-lang.org")
|
||||
//! .await?
|
||||
//! .text()
|
||||
//! .await?;
|
||||
//!
|
||||
//! println!("body = {:?}", body);
|
||||
//! # Ok(())
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! Additionally, reqwest's [`Response`][response] struct implements Rust's
|
||||
//! `Read` trait, so many useful standard library and third party crates will
|
||||
//! have convenience methods that take a `Response` anywhere `T: Read` is
|
||||
//! acceptable.
|
||||
//!
|
||||
//! **NOTE**: If you plan to perform multiple requests, it is best to create a
|
||||
//! [`Client`][client] and reuse it, taking advantage of keep-alive connection
|
||||
//! pooling.
|
||||
@@ -57,16 +53,17 @@
|
||||
//! by using the `body()` method of a [`RequestBuilder`][builder]. This lets you set the
|
||||
//! exact raw bytes of what the body should be. It accepts various types,
|
||||
//! including `String`, `Vec<u8>`, and `File`. If you wish to pass a custom
|
||||
//! Reader, you can use the `reqwest::Body::new()` constructor.
|
||||
//! type, you can use the `reqwest::Body` constructors.
|
||||
//!
|
||||
//! ```rust
|
||||
//! # use reqwest::Error;
|
||||
//! #
|
||||
//! # fn run() -> Result<(), Error> {
|
||||
//! # async fn run() -> Result<(), Error> {
|
||||
//! let client = reqwest::Client::new();
|
||||
//! let res = client.post("http://httpbin.org/post")
|
||||
//! .body("the exact body that is sent")
|
||||
//! .send()?;
|
||||
//! .send()
|
||||
//! .await?;
|
||||
//! # Ok(())
|
||||
//! # }
|
||||
//! ```
|
||||
@@ -82,13 +79,14 @@
|
||||
//! ```rust
|
||||
//! # use reqwest::Error;
|
||||
//! #
|
||||
//! # fn run() -> Result<(), Error> {
|
||||
//! # async fn run() -> Result<(), Error> {
|
||||
//! // This will POST a body of `foo=bar&baz=quux`
|
||||
//! let params = [("foo", "bar"), ("baz", "quux")];
|
||||
//! let client = reqwest::Client::new();
|
||||
//! let res = client.post("http://httpbin.org/post")
|
||||
//! .form(¶ms)
|
||||
//! .send()?;
|
||||
//! .send()
|
||||
//! .await?;
|
||||
//! # Ok(())
|
||||
//! # }
|
||||
//! ```
|
||||
@@ -103,7 +101,7 @@
|
||||
//! # use reqwest::Error;
|
||||
//! # use std::collections::HashMap;
|
||||
//! #
|
||||
//! # fn run() -> Result<(), Error> {
|
||||
//! # async fn run() -> Result<(), Error> {
|
||||
//! // This will POST a body of `{"lang":"rust","body":"json"}`
|
||||
//! let mut map = HashMap::new();
|
||||
//! map.insert("lang", "rust");
|
||||
@@ -112,7 +110,8 @@
|
||||
//! let client = reqwest::Client::new();
|
||||
//! let res = client.post("http://httpbin.org/post")
|
||||
//! .json(&map)
|
||||
//! .send()?;
|
||||
//! .send()
|
||||
//! .await?;
|
||||
//! # Ok(())
|
||||
//! # }
|
||||
//! ```
|
||||
@@ -157,8 +156,6 @@
|
||||
//! `native-tls` library to connect over HTTPS.
|
||||
//! - **default-tls-vendored**: Enables the `vendored` feature of `native-tls`.
|
||||
//! - **rustls-tls**: Provides TLS support via the `rustls` library.
|
||||
//! - **socks**: Provides SOCKS5 proxy support.
|
||||
//! - **hyper-011**: Provides support for hyper's old typed headers.
|
||||
//!
|
||||
//!
|
||||
//! [hyper]: http://hyper.rs
|
||||
@@ -171,12 +168,11 @@
|
||||
//! [Proxy]: ./struct.Proxy.html
|
||||
//! [cargo-features]: https://doc.rust-lang.org/stable/cargo/reference/manifest.html#the-features-section
|
||||
|
||||
////! - **socks**: Provides SOCKS5 proxy support.
|
||||
////! - **trust-dns**: Enables a trust-dns async resolver instead of default
|
||||
////! threadpool using `getaddrinfo`.
|
||||
|
||||
extern crate cookie as cookie_crate;
|
||||
#[cfg(feature = "hyper-011")]
|
||||
pub use hyper_old_types as hyper_011;
|
||||
|
||||
#[cfg(test)]
|
||||
#[macro_use]
|
||||
@@ -191,14 +187,17 @@ pub use hyper::{StatusCode, Version};
|
||||
pub use url::ParseError as UrlError;
|
||||
pub use url::Url;
|
||||
|
||||
pub use self::body::Body;
|
||||
pub use self::client::{Client, ClientBuilder};
|
||||
pub use self::r#async::{
|
||||
multipart, Body, Client, ClientBuilder, Decoder, Request, RequestBuilder, Response,
|
||||
};
|
||||
//pub use self::body::Body;
|
||||
//pub use self::client::{Client, ClientBuilder};
|
||||
pub use self::error::{Error, Result};
|
||||
pub use self::into_url::IntoUrl;
|
||||
pub use self::proxy::Proxy;
|
||||
pub use self::redirect::{RedirectAction, RedirectAttempt, RedirectPolicy};
|
||||
pub use self::request::{Request, RequestBuilder};
|
||||
pub use self::response::Response;
|
||||
//pub use self::request::{Request, RequestBuilder};
|
||||
//pub use self::response::Response;
|
||||
#[cfg(feature = "tls")]
|
||||
pub use self::tls::{Certificate, Identity};
|
||||
|
||||
@@ -207,8 +206,7 @@ pub use self::tls::{Certificate, Identity};
|
||||
mod error;
|
||||
|
||||
mod async_impl;
|
||||
mod body;
|
||||
mod client;
|
||||
pub mod blocking;
|
||||
mod connect;
|
||||
pub mod cookie;
|
||||
//#[cfg(feature = "trust-dns")]
|
||||
@@ -216,19 +214,16 @@ pub mod cookie;
|
||||
mod into_url;
|
||||
mod proxy;
|
||||
mod redirect;
|
||||
mod request;
|
||||
mod response;
|
||||
#[cfg(feature = "tls")]
|
||||
mod tls;
|
||||
mod wait;
|
||||
|
||||
pub mod multipart;
|
||||
//pub mod multipart;
|
||||
|
||||
/// An 'async' implementation of the reqwest `Client`.
|
||||
#[doc(hidden)]
|
||||
#[deprecated(note = "types moved to top of crate")]
|
||||
pub mod r#async {
|
||||
pub use crate::async_impl::{
|
||||
multipart, Body, Chunk, Client, ClientBuilder, Decoder, Request, RequestBuilder, Response,
|
||||
ResponseBuilderExt,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -244,12 +239,11 @@ pub mod r#async {
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # fn run() -> Result<(), reqwest::Error> {
|
||||
/// let body = reqwest::get("https://www.rust-lang.org")?
|
||||
/// .text()?;
|
||||
/// # async fn run() -> Result<(), reqwest::Error> {
|
||||
/// let body = reqwest::get("https://www.rust-lang.org").await?
|
||||
/// .text().await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// # fn main() { }
|
||||
/// ```
|
||||
///
|
||||
/// # Errors
|
||||
@@ -261,8 +255,8 @@ pub mod r#async {
|
||||
/// - there was an error while sending request
|
||||
/// - redirect loop was detected
|
||||
/// - redirect limit was exhausted
|
||||
pub fn get<T: IntoUrl>(url: T) -> crate::Result<Response> {
|
||||
Client::builder().build()?.get(url).send()
|
||||
pub async fn get<T: IntoUrl>(url: T) -> crate::Result<Response> {
|
||||
Client::builder().build()?.get(url).send().await
|
||||
}
|
||||
|
||||
fn _assert_impls() {
|
||||
|
||||
325
tests/async.rs
325
tests/async.rs
@@ -1,325 +0,0 @@
|
||||
#[macro_use]
|
||||
mod support;
|
||||
|
||||
use std::io::Write;
|
||||
use std::time::Duration;
|
||||
|
||||
use futures::TryStreamExt;
|
||||
|
||||
use reqwest::r#async::multipart::{Form, Part};
|
||||
use reqwest::r#async::{Body, Client};
|
||||
|
||||
use bytes::Bytes;
|
||||
|
||||
#[tokio::test]
|
||||
async fn gzip_response() {
|
||||
gzip_case(10_000, 4096).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn gzip_single_byte_chunks() {
|
||||
gzip_case(10, 1).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn response_text() {
|
||||
let _ = env_logger::try_init();
|
||||
|
||||
let server = server! {
|
||||
request: b"\
|
||||
GET /text HTTP/1.1\r\n\
|
||||
user-agent: $USERAGENT\r\n\
|
||||
accept: */*\r\n\
|
||||
accept-encoding: gzip\r\n\
|
||||
host: $HOST\r\n\
|
||||
\r\n\
|
||||
",
|
||||
response: b"\
|
||||
HTTP/1.1 200 OK\r\n\
|
||||
Content-Length: 5\r\n\
|
||||
\r\n\
|
||||
Hello\
|
||||
"
|
||||
};
|
||||
|
||||
let client = Client::new();
|
||||
|
||||
let mut res = client
|
||||
.get(&format!("http://{}/text", server.addr()))
|
||||
.send()
|
||||
.await
|
||||
.expect("Failed to get");
|
||||
let text = res.text().await.expect("Failed to get text");
|
||||
assert_eq!("Hello", text);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn response_json() {
|
||||
let _ = env_logger::try_init();
|
||||
|
||||
let server = server! {
|
||||
request: b"\
|
||||
GET /json HTTP/1.1\r\n\
|
||||
user-agent: $USERAGENT\r\n\
|
||||
accept: */*\r\n\
|
||||
accept-encoding: gzip\r\n\
|
||||
host: $HOST\r\n\
|
||||
\r\n\
|
||||
",
|
||||
response: b"\
|
||||
HTTP/1.1 200 OK\r\n\
|
||||
Content-Length: 7\r\n\
|
||||
\r\n\
|
||||
\"Hello\"\
|
||||
"
|
||||
};
|
||||
|
||||
let client = Client::new();
|
||||
|
||||
let mut res = client
|
||||
.get(&format!("http://{}/json", server.addr()))
|
||||
.send()
|
||||
.await
|
||||
.expect("Failed to get");
|
||||
let text = res.json::<String>().await.expect("Failed to get json");
|
||||
assert_eq!("Hello", text);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn multipart() {
|
||||
let _ = env_logger::try_init();
|
||||
|
||||
let stream = futures::stream::once(futures::future::ready::<Result<_, hyper::Error>>(Ok(
|
||||
hyper::Chunk::from("part1 part2".to_owned()),
|
||||
)));
|
||||
let part = Part::stream(stream);
|
||||
|
||||
let form = Form::new().text("foo", "bar").part("part_stream", part);
|
||||
|
||||
let expected_body = format!(
|
||||
"\
|
||||
24\r\n\
|
||||
--{0}\r\n\r\n\
|
||||
2E\r\n\
|
||||
Content-Disposition: form-data; name=\"foo\"\r\n\r\n\r\n\
|
||||
3\r\n\
|
||||
bar\r\n\
|
||||
2\r\n\
|
||||
\r\n\r\n\
|
||||
24\r\n\
|
||||
--{0}\r\n\r\n\
|
||||
36\r\n\
|
||||
Content-Disposition: form-data; name=\"part_stream\"\r\n\r\n\r\n\
|
||||
B\r\n\
|
||||
part1 part2\r\n\
|
||||
2\r\n\
|
||||
\r\n\r\n\
|
||||
26\r\n\
|
||||
--{0}--\r\n\r\n\
|
||||
0\r\n\r\n\
|
||||
",
|
||||
form.boundary()
|
||||
);
|
||||
|
||||
let server = server! {
|
||||
request: format!("\
|
||||
POST /multipart/1 HTTP/1.1\r\n\
|
||||
content-type: multipart/form-data; boundary={}\r\n\
|
||||
user-agent: $USERAGENT\r\n\
|
||||
accept: */*\r\n\
|
||||
accept-encoding: gzip\r\n\
|
||||
host: $HOST\r\n\
|
||||
transfer-encoding: chunked\r\n\
|
||||
\r\n\
|
||||
{}\
|
||||
", form.boundary(), expected_body),
|
||||
response: b"\
|
||||
HTTP/1.1 200 OK\r\n\
|
||||
Server: multipart\r\n\
|
||||
Content-Length: 0\r\n\
|
||||
\r\n\
|
||||
"
|
||||
};
|
||||
|
||||
let url = format!("http://{}/multipart/1", server.addr());
|
||||
|
||||
let client = Client::new();
|
||||
|
||||
let res = client
|
||||
.post(&url)
|
||||
.multipart(form)
|
||||
.send()
|
||||
.await
|
||||
.expect("Failed to post multipart");
|
||||
assert_eq!(res.url().as_str(), &url);
|
||||
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn request_timeout() {
|
||||
let _ = env_logger::try_init();
|
||||
|
||||
let server = server! {
|
||||
request: b"\
|
||||
GET /slow HTTP/1.1\r\n\
|
||||
user-agent: $USERAGENT\r\n\
|
||||
accept: */*\r\n\
|
||||
accept-encoding: gzip\r\n\
|
||||
host: $HOST\r\n\
|
||||
\r\n\
|
||||
",
|
||||
response: b"\
|
||||
HTTP/1.1 200 OK\r\n\
|
||||
Content-Length: 5\r\n\
|
||||
\r\n\
|
||||
Hello\
|
||||
",
|
||||
read_timeout: Duration::from_secs(2)
|
||||
};
|
||||
|
||||
let client = Client::builder()
|
||||
.timeout(Duration::from_millis(500))
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let url = format!("http://{}/slow", server.addr());
|
||||
|
||||
let res = client.get(&url).send().await;
|
||||
|
||||
let err = res.unwrap_err();
|
||||
|
||||
assert!(err.is_timeout());
|
||||
assert_eq!(err.url().map(|u| u.as_str()), Some(url.as_str()));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn response_timeout() {
|
||||
let _ = env_logger::try_init();
|
||||
|
||||
let server = server! {
|
||||
request: b"\
|
||||
GET /slow HTTP/1.1\r\n\
|
||||
user-agent: $USERAGENT\r\n\
|
||||
accept: */*\r\n\
|
||||
accept-encoding: gzip\r\n\
|
||||
host: $HOST\r\n\
|
||||
\r\n\
|
||||
",
|
||||
response: b"\
|
||||
HTTP/1.1 200 OK\r\n\
|
||||
Content-Length: 5\r\n\
|
||||
\r\n\
|
||||
Hello\
|
||||
",
|
||||
write_timeout: Duration::from_secs(2)
|
||||
};
|
||||
|
||||
let client = Client::builder()
|
||||
.timeout(Duration::from_millis(500))
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let url = format!("http://{}/slow", server.addr());
|
||||
let res = client.get(&url).send().await.expect("Failed to get");
|
||||
let body: Result<_, _> = res.into_body().try_concat().await;
|
||||
|
||||
let err = body.unwrap_err();
|
||||
|
||||
assert!(err.is_timeout());
|
||||
}
|
||||
|
||||
async fn gzip_case(response_size: usize, chunk_size: usize) {
|
||||
let content: String = (0..response_size)
|
||||
.into_iter()
|
||||
.map(|i| format!("test {}", i))
|
||||
.collect();
|
||||
let mut encoder = libflate::gzip::Encoder::new(Vec::new()).unwrap();
|
||||
match encoder.write(content.as_bytes()) {
|
||||
Ok(n) => assert!(n > 0, "Failed to write to encoder."),
|
||||
_ => panic!("Failed to gzip encode string."),
|
||||
};
|
||||
|
||||
let gzipped_content = encoder.finish().into_result().unwrap();
|
||||
|
||||
let mut response = format!(
|
||||
"\
|
||||
HTTP/1.1 200 OK\r\n\
|
||||
Server: test-accept\r\n\
|
||||
Content-Encoding: gzip\r\n\
|
||||
Content-Length: {}\r\n\
|
||||
\r\n",
|
||||
&gzipped_content.len()
|
||||
)
|
||||
.into_bytes();
|
||||
response.extend(&gzipped_content);
|
||||
|
||||
let server = server! {
|
||||
request: b"\
|
||||
GET /gzip HTTP/1.1\r\n\
|
||||
user-agent: $USERAGENT\r\n\
|
||||
accept: */*\r\n\
|
||||
accept-encoding: gzip\r\n\
|
||||
host: $HOST\r\n\
|
||||
\r\n\
|
||||
",
|
||||
chunk_size: chunk_size,
|
||||
write_timeout: Duration::from_millis(10),
|
||||
response: response
|
||||
};
|
||||
|
||||
let client = Client::new();
|
||||
|
||||
let mut res = client
|
||||
.get(&format!("http://{}/gzip", server.addr()))
|
||||
.send()
|
||||
.await
|
||||
.expect("response");
|
||||
|
||||
let body = res.text().await.expect("text");
|
||||
assert_eq!(body, content);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn body_stream() {
|
||||
let _ = env_logger::try_init();
|
||||
|
||||
let source = futures::stream::iter::<Vec<Result<Bytes, std::io::Error>>>(vec![
|
||||
Ok(Bytes::from_static(b"123")),
|
||||
Ok(Bytes::from_static(b"4567")),
|
||||
]);
|
||||
|
||||
let expected_body = "3\r\n123\r\n4\r\n4567\r\n0\r\n\r\n";
|
||||
|
||||
let server = server! {
|
||||
request: format!("\
|
||||
POST /post HTTP/1.1\r\n\
|
||||
user-agent: $USERAGENT\r\n\
|
||||
accept: */*\r\n\
|
||||
accept-encoding: gzip\r\n\
|
||||
host: $HOST\r\n\
|
||||
transfer-encoding: chunked\r\n\
|
||||
\r\n\
|
||||
{}\
|
||||
", expected_body),
|
||||
response: b"\
|
||||
HTTP/1.1 200 OK\r\n\
|
||||
Server: post\r\n\
|
||||
Content-Length: 7\r\n\
|
||||
\r\n\
|
||||
"
|
||||
};
|
||||
|
||||
let url = format!("http://{}/post", server.addr());
|
||||
|
||||
let client = Client::new();
|
||||
|
||||
let res = client
|
||||
.post(&url)
|
||||
.body(Body::wrap_stream(source))
|
||||
.send()
|
||||
.await
|
||||
.expect("Failed to post");
|
||||
|
||||
assert_eq!(res.url().as_str(), &url);
|
||||
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||
}
|
||||
@@ -1,57 +1,65 @@
|
||||
#[cfg(feature = "tls")]
|
||||
#[test]
|
||||
fn test_badssl_modern() {
|
||||
#[tokio::test]
|
||||
async fn test_badssl_modern() {
|
||||
let text = reqwest::get("https://mozilla-modern.badssl.com/")
|
||||
.await
|
||||
.unwrap()
|
||||
.text()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert!(text.contains("<title>mozilla-modern.badssl.com</title>"));
|
||||
}
|
||||
|
||||
#[cfg(feature = "rustls-tls")]
|
||||
#[test]
|
||||
fn test_rustls_badssl_modern() {
|
||||
#[tokio::test]
|
||||
async fn test_rustls_badssl_modern() {
|
||||
let text = reqwest::Client::builder()
|
||||
.use_rustls_tls()
|
||||
.build()
|
||||
.unwrap()
|
||||
.get("https://mozilla-modern.badssl.com/")
|
||||
.send()
|
||||
.await
|
||||
.unwrap()
|
||||
.text()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert!(text.contains("<title>mozilla-modern.badssl.com</title>"));
|
||||
}
|
||||
|
||||
#[cfg(feature = "tls")]
|
||||
#[test]
|
||||
fn test_badssl_self_signed() {
|
||||
#[tokio::test]
|
||||
async fn test_badssl_self_signed() {
|
||||
let text = reqwest::Client::builder()
|
||||
.danger_accept_invalid_certs(true)
|
||||
.build()
|
||||
.unwrap()
|
||||
.get("https://self-signed.badssl.com/")
|
||||
.send()
|
||||
.await
|
||||
.unwrap()
|
||||
.text()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert!(text.contains("<title>self-signed.badssl.com</title>"));
|
||||
}
|
||||
|
||||
#[cfg(feature = "default-tls")]
|
||||
#[test]
|
||||
fn test_badssl_wrong_host() {
|
||||
#[tokio::test]
|
||||
async fn test_badssl_wrong_host() {
|
||||
let text = reqwest::Client::builder()
|
||||
.danger_accept_invalid_hostnames(true)
|
||||
.build()
|
||||
.unwrap()
|
||||
.get("https://wrong.host.badssl.com/")
|
||||
.send()
|
||||
.await
|
||||
.unwrap()
|
||||
.text()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert!(text.contains("<title>wrong.host.badssl.com</title>"));
|
||||
@@ -61,7 +69,8 @@ fn test_badssl_wrong_host() {
|
||||
.build()
|
||||
.unwrap()
|
||||
.get("https://self-signed.badssl.com/")
|
||||
.send();
|
||||
.send()
|
||||
.await;
|
||||
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
512
tests/blocking.rs
Normal file
512
tests/blocking.rs
Normal file
@@ -0,0 +1,512 @@
|
||||
#[macro_use]
|
||||
mod support;
|
||||
|
||||
#[test]
|
||||
fn test_response_text() {
|
||||
let server = server! {
|
||||
request: b"\
|
||||
GET /text HTTP/1.1\r\n\
|
||||
user-agent: $USERAGENT\r\n\
|
||||
accept: */*\r\n\
|
||||
accept-encoding: gzip\r\n\
|
||||
host: $HOST\r\n\
|
||||
\r\n\
|
||||
",
|
||||
response: b"\
|
||||
HTTP/1.1 200 OK\r\n\
|
||||
Server: test\r\n\
|
||||
Content-Length: 5\r\n\
|
||||
\r\n\
|
||||
Hello\
|
||||
"
|
||||
};
|
||||
|
||||
let url = format!("http://{}/text", server.addr());
|
||||
let mut res = reqwest::blocking::get(&url).unwrap();
|
||||
assert_eq!(res.url().as_str(), &url);
|
||||
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||
assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test");
|
||||
assert_eq!(
|
||||
res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(),
|
||||
&"5"
|
||||
);
|
||||
|
||||
let body = res.text().unwrap();
|
||||
assert_eq!(b"Hello", body.as_bytes());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_response_non_utf_8_text() {
|
||||
let server = server! {
|
||||
request: b"\
|
||||
GET /text HTTP/1.1\r\n\
|
||||
user-agent: $USERAGENT\r\n\
|
||||
accept: */*\r\n\
|
||||
accept-encoding: gzip\r\n\
|
||||
host: $HOST\r\n\
|
||||
\r\n\
|
||||
",
|
||||
response: b"\
|
||||
HTTP/1.1 200 OK\r\n\
|
||||
Server: test\r\n\
|
||||
Content-Length: 4\r\n\
|
||||
Content-Type: text/plain; charset=gbk\r\n\
|
||||
\r\n\
|
||||
\xc4\xe3\xba\xc3\
|
||||
"
|
||||
};
|
||||
|
||||
let url = format!("http://{}/text", server.addr());
|
||||
let mut res = reqwest::blocking::get(&url).unwrap();
|
||||
assert_eq!(res.url().as_str(), &url);
|
||||
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||
assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test");
|
||||
assert_eq!(
|
||||
res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(),
|
||||
&"4"
|
||||
);
|
||||
|
||||
let body = res.text().unwrap();
|
||||
assert_eq!("你好", &body);
|
||||
assert_eq!(b"\xe4\xbd\xa0\xe5\xa5\xbd", body.as_bytes()); // Now it's utf-8
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_response_json() {
|
||||
let server = server! {
|
||||
request: b"\
|
||||
GET /json HTTP/1.1\r\n\
|
||||
user-agent: $USERAGENT\r\n\
|
||||
accept: */*\r\n\
|
||||
accept-encoding: gzip\r\n\
|
||||
host: $HOST\r\n\
|
||||
\r\n\
|
||||
",
|
||||
response: b"\
|
||||
HTTP/1.1 200 OK\r\n\
|
||||
Server: test\r\n\
|
||||
Content-Length: 7\r\n\
|
||||
\r\n\
|
||||
\"Hello\"\
|
||||
"
|
||||
};
|
||||
|
||||
let url = format!("http://{}/json", server.addr());
|
||||
let mut res = reqwest::blocking::get(&url).unwrap();
|
||||
assert_eq!(res.url().as_str(), &url);
|
||||
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||
assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test");
|
||||
assert_eq!(
|
||||
res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(),
|
||||
&"7"
|
||||
);
|
||||
|
||||
let body = res.json::<String>().unwrap();
|
||||
assert_eq!("Hello", body);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_response_copy_to() {
|
||||
let server = server! {
|
||||
request: b"\
|
||||
GET /1 HTTP/1.1\r\n\
|
||||
user-agent: $USERAGENT\r\n\
|
||||
accept: */*\r\n\
|
||||
accept-encoding: gzip\r\n\
|
||||
host: $HOST\r\n\
|
||||
\r\n\
|
||||
",
|
||||
response: b"\
|
||||
HTTP/1.1 200 OK\r\n\
|
||||
Server: test\r\n\
|
||||
Content-Length: 5\r\n\
|
||||
\r\n\
|
||||
Hello\
|
||||
"
|
||||
};
|
||||
|
||||
let url = format!("http://{}/1", server.addr());
|
||||
let mut res = reqwest::blocking::get(&url).unwrap();
|
||||
assert_eq!(res.url().as_str(), &url);
|
||||
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||
assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test");
|
||||
assert_eq!(
|
||||
res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(),
|
||||
&"5"
|
||||
);
|
||||
|
||||
assert_eq!("Hello".to_owned(), res.text().unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get() {
|
||||
let server = server! {
|
||||
request: b"\
|
||||
GET /1 HTTP/1.1\r\n\
|
||||
user-agent: $USERAGENT\r\n\
|
||||
accept: */*\r\n\
|
||||
accept-encoding: gzip\r\n\
|
||||
host: $HOST\r\n\
|
||||
\r\n\
|
||||
",
|
||||
response: b"\
|
||||
HTTP/1.1 200 OK\r\n\
|
||||
Server: test\r\n\
|
||||
Content-Length: 0\r\n\
|
||||
\r\n\
|
||||
"
|
||||
};
|
||||
|
||||
let url = format!("http://{}/1", server.addr());
|
||||
let mut res = reqwest::blocking::get(&url).unwrap();
|
||||
|
||||
assert_eq!(res.url().as_str(), &url);
|
||||
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||
assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test");
|
||||
assert_eq!(
|
||||
res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(),
|
||||
&"0"
|
||||
);
|
||||
assert_eq!(res.remote_addr(), Some(server.addr()));
|
||||
|
||||
assert_eq!(res.text().unwrap().len(), 0)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_post() {
|
||||
let server = server! {
|
||||
request: b"\
|
||||
POST /2 HTTP/1.1\r\n\
|
||||
content-length: 5\r\n\
|
||||
user-agent: $USERAGENT\r\n\
|
||||
accept: */*\r\n\
|
||||
accept-encoding: gzip\r\n\
|
||||
host: $HOST\r\n\
|
||||
\r\n\
|
||||
Hello\
|
||||
",
|
||||
response: b"\
|
||||
HTTP/1.1 200 OK\r\n\
|
||||
Server: post\r\n\
|
||||
Content-Length: 0\r\n\
|
||||
\r\n\
|
||||
"
|
||||
};
|
||||
|
||||
let url = format!("http://{}/2", server.addr());
|
||||
let mut res = reqwest::blocking::Client::new()
|
||||
.post(&url)
|
||||
.body("Hello")
|
||||
.send()
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(res.url().as_str(), &url);
|
||||
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||
assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"post");
|
||||
assert_eq!(
|
||||
res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(),
|
||||
&"0"
|
||||
);
|
||||
|
||||
assert_eq!(res.text().unwrap().len(), 0)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_post_form() {
|
||||
let server = server! {
|
||||
request: b"\
|
||||
POST /form HTTP/1.1\r\n\
|
||||
content-type: application/x-www-form-urlencoded\r\n\
|
||||
content-length: 24\r\n\
|
||||
user-agent: $USERAGENT\r\n\
|
||||
accept: */*\r\n\
|
||||
accept-encoding: gzip\r\n\
|
||||
host: $HOST\r\n\
|
||||
\r\n\
|
||||
hello=world&sean=monstar\
|
||||
",
|
||||
response: b"\
|
||||
HTTP/1.1 200 OK\r\n\
|
||||
Server: post-form\r\n\
|
||||
Content-Length: 0\r\n\
|
||||
\r\n\
|
||||
"
|
||||
};
|
||||
|
||||
let form = &[("hello", "world"), ("sean", "monstar")];
|
||||
|
||||
let url = format!("http://{}/form", server.addr());
|
||||
let res = reqwest::blocking::Client::new()
|
||||
.post(&url)
|
||||
.form(form)
|
||||
.send()
|
||||
.expect("request send");
|
||||
|
||||
assert_eq!(res.url().as_str(), &url);
|
||||
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||
}
|
||||
|
||||
/// Calling `Response::error_for_status`` on a response with status in 4xx
|
||||
/// returns a error.
|
||||
#[test]
|
||||
fn test_error_for_status_4xx() {
|
||||
let server = server! {
|
||||
request: b"\
|
||||
GET /1 HTTP/1.1\r\n\
|
||||
user-agent: $USERAGENT\r\n\
|
||||
accept: */*\r\n\
|
||||
accept-encoding: gzip\r\n\
|
||||
host: $HOST\r\n\
|
||||
\r\n\
|
||||
",
|
||||
response: b"\
|
||||
HTTP/1.1 400 OK\r\n\
|
||||
Server: test\r\n\
|
||||
Content-Length: 0\r\n\
|
||||
\r\n\
|
||||
"
|
||||
};
|
||||
|
||||
let url = format!("http://{}/1", server.addr());
|
||||
let res = reqwest::blocking::get(&url).unwrap();
|
||||
|
||||
let err = res.error_for_status().err().unwrap();
|
||||
assert!(err.is_client_error());
|
||||
assert_eq!(err.status(), Some(reqwest::StatusCode::BAD_REQUEST));
|
||||
}
|
||||
|
||||
/// Calling `Response::error_for_status`` on a response with status in 5xx
|
||||
/// returns a error.
|
||||
#[test]
|
||||
fn test_error_for_status_5xx() {
|
||||
let server = server! {
|
||||
request: b"\
|
||||
GET /1 HTTP/1.1\r\n\
|
||||
user-agent: $USERAGENT\r\n\
|
||||
accept: */*\r\n\
|
||||
accept-encoding: gzip\r\n\
|
||||
host: $HOST\r\n\
|
||||
\r\n\
|
||||
",
|
||||
response: b"\
|
||||
HTTP/1.1 500 OK\r\n\
|
||||
Server: test\r\n\
|
||||
Content-Length: 0\r\n\
|
||||
\r\n\
|
||||
"
|
||||
};
|
||||
|
||||
let url = format!("http://{}/1", server.addr());
|
||||
let res = reqwest::blocking::get(&url).unwrap();
|
||||
|
||||
let err = res.error_for_status().err().unwrap();
|
||||
assert!(err.is_server_error());
|
||||
assert_eq!(
|
||||
err.status(),
|
||||
Some(reqwest::StatusCode::INTERNAL_SERVER_ERROR)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_default_headers() {
|
||||
use reqwest::header;
|
||||
let mut headers = header::HeaderMap::with_capacity(1);
|
||||
headers.insert(header::COOKIE, header::HeaderValue::from_static("a=b;c=d"));
|
||||
let client = reqwest::blocking::Client::builder()
|
||||
.default_headers(headers)
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let server = server! {
|
||||
request: b"\
|
||||
GET /1 HTTP/1.1\r\n\
|
||||
user-agent: $USERAGENT\r\n\
|
||||
accept: */*\r\n\
|
||||
cookie: a=b;c=d\r\n\
|
||||
accept-encoding: gzip\r\n\
|
||||
host: $HOST\r\n\
|
||||
\r\n\
|
||||
",
|
||||
response: b"\
|
||||
HTTP/1.1 200 OK\r\n\
|
||||
Server: test\r\n\
|
||||
Content-Length: 0\r\n\
|
||||
\r\n\
|
||||
"
|
||||
};
|
||||
|
||||
let url = format!("http://{}/1", server.addr());
|
||||
let res = client.get(&url).send().unwrap();
|
||||
|
||||
assert_eq!(res.url().as_str(), &url);
|
||||
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||
assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test");
|
||||
assert_eq!(
|
||||
res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(),
|
||||
&"0"
|
||||
);
|
||||
|
||||
let server = server! {
|
||||
request: b"\
|
||||
GET /2 HTTP/1.1\r\n\
|
||||
user-agent: $USERAGENT\r\n\
|
||||
accept: */*\r\n\
|
||||
cookie: a=b;c=d\r\n\
|
||||
accept-encoding: gzip\r\n\
|
||||
host: $HOST\r\n\
|
||||
\r\n\
|
||||
",
|
||||
response: b"\
|
||||
HTTP/1.1 200 OK\r\n\
|
||||
Server: test\r\n\
|
||||
Content-Length: 0\r\n\
|
||||
\r\n\
|
||||
"
|
||||
};
|
||||
|
||||
let url = format!("http://{}/2", server.addr());
|
||||
let res = client.get(&url).send().unwrap();
|
||||
|
||||
assert_eq!(res.url().as_str(), &url);
|
||||
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||
assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test");
|
||||
assert_eq!(
|
||||
res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(),
|
||||
&"0"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_override_default_headers() {
|
||||
use reqwest::header;
|
||||
let mut headers = header::HeaderMap::with_capacity(1);
|
||||
headers.insert(
|
||||
header::AUTHORIZATION,
|
||||
header::HeaderValue::from_static("iamatoken"),
|
||||
);
|
||||
let client = reqwest::blocking::Client::builder()
|
||||
.default_headers(headers)
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let server = server! {
|
||||
request: b"\
|
||||
GET /3 HTTP/1.1\r\n\
|
||||
authorization: secret\r\n\
|
||||
user-agent: $USERAGENT\r\n\
|
||||
accept: */*\r\n\
|
||||
accept-encoding: gzip\r\n\
|
||||
host: $HOST\r\n\
|
||||
\r\n\
|
||||
",
|
||||
response: b"\
|
||||
HTTP/1.1 200 OK\r\n\
|
||||
Server: test\r\n\
|
||||
Content-Length: 0\r\n\
|
||||
\r\n\
|
||||
"
|
||||
};
|
||||
|
||||
let url = format!("http://{}/3", server.addr());
|
||||
let res = client
|
||||
.get(&url)
|
||||
.header(
|
||||
header::AUTHORIZATION,
|
||||
header::HeaderValue::from_static("secret"),
|
||||
)
|
||||
.send()
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(res.url().as_str(), &url);
|
||||
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||
assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test");
|
||||
assert_eq!(
|
||||
res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(),
|
||||
&"0"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_appended_headers_not_overwritten() {
|
||||
let client = reqwest::blocking::Client::new();
|
||||
|
||||
let server = server! {
|
||||
request: b"\
|
||||
GET /4 HTTP/1.1\r\n\
|
||||
accept: application/json\r\n\
|
||||
accept: application/json+hal\r\n\
|
||||
user-agent: $USERAGENT\r\n\
|
||||
accept-encoding: gzip\r\n\
|
||||
host: $HOST\r\n\
|
||||
\r\n\
|
||||
",
|
||||
response: b"\
|
||||
HTTP/1.1 200 OK\r\n\
|
||||
Server: test\r\n\
|
||||
Content-Length: 0\r\n\
|
||||
\r\n\
|
||||
"
|
||||
};
|
||||
|
||||
let url = format!("http://{}/4", server.addr());
|
||||
let res = client
|
||||
.get(&url)
|
||||
.header(header::ACCEPT, "application/json")
|
||||
.header(header::ACCEPT, "application/json+hal")
|
||||
.send()
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(res.url().as_str(), &url);
|
||||
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||
assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test");
|
||||
assert_eq!(
|
||||
res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(),
|
||||
&"0"
|
||||
);
|
||||
|
||||
// make sure this also works with default headers
|
||||
use reqwest::header;
|
||||
let mut headers = header::HeaderMap::with_capacity(1);
|
||||
headers.insert(
|
||||
header::ACCEPT,
|
||||
header::HeaderValue::from_static("text/html"),
|
||||
);
|
||||
let client = reqwest::blocking::Client::builder()
|
||||
.default_headers(headers)
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let server = server! {
|
||||
request: b"\
|
||||
GET /4 HTTP/1.1\r\n\
|
||||
accept: application/json\r\n\
|
||||
accept: application/json+hal\r\n\
|
||||
user-agent: $USERAGENT\r\n\
|
||||
accept-encoding: gzip\r\n\
|
||||
host: $HOST\r\n\
|
||||
\r\n\
|
||||
",
|
||||
response: b"\
|
||||
HTTP/1.1 200 OK\r\n\
|
||||
Server: test\r\n\
|
||||
Content-Length: 0\r\n\
|
||||
\r\n\
|
||||
"
|
||||
};
|
||||
|
||||
let url = format!("http://{}/4", server.addr());
|
||||
let res = client
|
||||
.get(&url)
|
||||
.header(header::ACCEPT, "application/json")
|
||||
.header(header::ACCEPT, "application/json+hal")
|
||||
.send()
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(res.url().as_str(), &url);
|
||||
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||
assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test");
|
||||
assert_eq!(
|
||||
res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(),
|
||||
&"0"
|
||||
);
|
||||
}
|
||||
661
tests/client.rs
661
tests/client.rs
@@ -1,8 +1,30 @@
|
||||
#[macro_use]
|
||||
mod support;
|
||||
|
||||
#[test]
|
||||
fn test_response_text() {
|
||||
use std::io::Write;
|
||||
use std::time::Duration;
|
||||
|
||||
use futures::TryStreamExt;
|
||||
|
||||
use reqwest::multipart::{Form, Part};
|
||||
use reqwest::{Body, Client};
|
||||
|
||||
use bytes::Bytes;
|
||||
|
||||
#[tokio::test]
|
||||
async fn gzip_response() {
|
||||
gzip_case(10_000, 4096).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn gzip_single_byte_chunks() {
|
||||
gzip_case(10, 1).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn response_text() {
|
||||
let _ = env_logger::try_init();
|
||||
|
||||
let server = server! {
|
||||
request: b"\
|
||||
GET /text HTTP/1.1\r\n\
|
||||
@@ -14,65 +36,27 @@ fn test_response_text() {
|
||||
",
|
||||
response: b"\
|
||||
HTTP/1.1 200 OK\r\n\
|
||||
Server: test\r\n\
|
||||
Content-Length: 5\r\n\
|
||||
\r\n\
|
||||
Hello\
|
||||
"
|
||||
};
|
||||
|
||||
let url = format!("http://{}/text", server.addr());
|
||||
let mut res = reqwest::get(&url).unwrap();
|
||||
assert_eq!(res.url().as_str(), &url);
|
||||
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||
assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test");
|
||||
assert_eq!(
|
||||
res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(),
|
||||
&"5"
|
||||
);
|
||||
let client = Client::new();
|
||||
|
||||
let body = res.text().unwrap();
|
||||
assert_eq!(b"Hello", body.as_bytes());
|
||||
let mut res = client
|
||||
.get(&format!("http://{}/text", server.addr()))
|
||||
.send()
|
||||
.await
|
||||
.expect("Failed to get");
|
||||
let text = res.text().await.expect("Failed to get text");
|
||||
assert_eq!("Hello", text);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_response_non_utf_8_text() {
|
||||
let server = server! {
|
||||
request: b"\
|
||||
GET /text HTTP/1.1\r\n\
|
||||
user-agent: $USERAGENT\r\n\
|
||||
accept: */*\r\n\
|
||||
accept-encoding: gzip\r\n\
|
||||
host: $HOST\r\n\
|
||||
\r\n\
|
||||
",
|
||||
response: b"\
|
||||
HTTP/1.1 200 OK\r\n\
|
||||
Server: test\r\n\
|
||||
Content-Length: 4\r\n\
|
||||
Content-Type: text/plain; charset=gbk\r\n\
|
||||
\r\n\
|
||||
\xc4\xe3\xba\xc3\
|
||||
"
|
||||
};
|
||||
#[tokio::test]
|
||||
async fn response_json() {
|
||||
let _ = env_logger::try_init();
|
||||
|
||||
let url = format!("http://{}/text", server.addr());
|
||||
let mut res = reqwest::get(&url).unwrap();
|
||||
assert_eq!(res.url().as_str(), &url);
|
||||
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||
assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test");
|
||||
assert_eq!(
|
||||
res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(),
|
||||
&"4"
|
||||
);
|
||||
|
||||
let body = res.text().unwrap();
|
||||
assert_eq!("你好", &body);
|
||||
assert_eq!(b"\xe4\xbd\xa0\xe5\xa5\xbd", body.as_bytes()); // Now it's utf-8
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_response_json() {
|
||||
let server = server! {
|
||||
request: b"\
|
||||
GET /json HTTP/1.1\r\n\
|
||||
@@ -84,32 +68,100 @@ fn test_response_json() {
|
||||
",
|
||||
response: b"\
|
||||
HTTP/1.1 200 OK\r\n\
|
||||
Server: test\r\n\
|
||||
Content-Length: 7\r\n\
|
||||
\r\n\
|
||||
\"Hello\"\
|
||||
"
|
||||
};
|
||||
|
||||
let url = format!("http://{}/json", server.addr());
|
||||
let mut res = reqwest::get(&url).unwrap();
|
||||
assert_eq!(res.url().as_str(), &url);
|
||||
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||
assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test");
|
||||
assert_eq!(
|
||||
res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(),
|
||||
&"7"
|
||||
);
|
||||
let client = Client::new();
|
||||
|
||||
let body = res.json::<String>().unwrap();
|
||||
assert_eq!("Hello", body);
|
||||
let mut res = client
|
||||
.get(&format!("http://{}/json", server.addr()))
|
||||
.send()
|
||||
.await
|
||||
.expect("Failed to get");
|
||||
let text = res.json::<String>().await.expect("Failed to get json");
|
||||
assert_eq!("Hello", text);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_response_copy_to() {
|
||||
#[tokio::test]
|
||||
async fn multipart() {
|
||||
let _ = env_logger::try_init();
|
||||
|
||||
let stream = futures::stream::once(futures::future::ready::<Result<_, hyper::Error>>(Ok(
|
||||
hyper::Chunk::from("part1 part2".to_owned()),
|
||||
)));
|
||||
let part = Part::stream(stream);
|
||||
|
||||
let form = Form::new().text("foo", "bar").part("part_stream", part);
|
||||
|
||||
let expected_body = format!(
|
||||
"\
|
||||
24\r\n\
|
||||
--{0}\r\n\r\n\
|
||||
2E\r\n\
|
||||
Content-Disposition: form-data; name=\"foo\"\r\n\r\n\r\n\
|
||||
3\r\n\
|
||||
bar\r\n\
|
||||
2\r\n\
|
||||
\r\n\r\n\
|
||||
24\r\n\
|
||||
--{0}\r\n\r\n\
|
||||
36\r\n\
|
||||
Content-Disposition: form-data; name=\"part_stream\"\r\n\r\n\r\n\
|
||||
B\r\n\
|
||||
part1 part2\r\n\
|
||||
2\r\n\
|
||||
\r\n\r\n\
|
||||
26\r\n\
|
||||
--{0}--\r\n\r\n\
|
||||
0\r\n\r\n\
|
||||
",
|
||||
form.boundary()
|
||||
);
|
||||
|
||||
let server = server! {
|
||||
request: format!("\
|
||||
POST /multipart/1 HTTP/1.1\r\n\
|
||||
content-type: multipart/form-data; boundary={}\r\n\
|
||||
user-agent: $USERAGENT\r\n\
|
||||
accept: */*\r\n\
|
||||
accept-encoding: gzip\r\n\
|
||||
host: $HOST\r\n\
|
||||
transfer-encoding: chunked\r\n\
|
||||
\r\n\
|
||||
{}\
|
||||
", form.boundary(), expected_body),
|
||||
response: b"\
|
||||
HTTP/1.1 200 OK\r\n\
|
||||
Server: multipart\r\n\
|
||||
Content-Length: 0\r\n\
|
||||
\r\n\
|
||||
"
|
||||
};
|
||||
|
||||
let url = format!("http://{}/multipart/1", server.addr());
|
||||
|
||||
let client = Client::new();
|
||||
|
||||
let res = client
|
||||
.post(&url)
|
||||
.multipart(form)
|
||||
.send()
|
||||
.await
|
||||
.expect("Failed to post multipart");
|
||||
assert_eq!(res.url().as_str(), &url);
|
||||
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn request_timeout() {
|
||||
let _ = env_logger::try_init();
|
||||
|
||||
let server = server! {
|
||||
request: b"\
|
||||
GET /1 HTTP/1.1\r\n\
|
||||
GET /slow HTTP/1.1\r\n\
|
||||
user-agent: $USERAGENT\r\n\
|
||||
accept: */*\r\n\
|
||||
accept-encoding: gzip\r\n\
|
||||
@@ -118,31 +170,35 @@ fn test_response_copy_to() {
|
||||
",
|
||||
response: b"\
|
||||
HTTP/1.1 200 OK\r\n\
|
||||
Server: test\r\n\
|
||||
Content-Length: 5\r\n\
|
||||
\r\n\
|
||||
Hello\
|
||||
"
|
||||
",
|
||||
read_timeout: Duration::from_secs(2)
|
||||
};
|
||||
|
||||
let url = format!("http://{}/1", server.addr());
|
||||
let mut res = reqwest::get(&url).unwrap();
|
||||
assert_eq!(res.url().as_str(), &url);
|
||||
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||
assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test");
|
||||
assert_eq!(
|
||||
res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(),
|
||||
&"5"
|
||||
);
|
||||
let client = Client::builder()
|
||||
.timeout(Duration::from_millis(500))
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
assert_eq!("Hello".to_owned(), res.text().unwrap());
|
||||
let url = format!("http://{}/slow", server.addr());
|
||||
|
||||
let res = client.get(&url).send().await;
|
||||
|
||||
let err = res.unwrap_err();
|
||||
|
||||
assert!(err.is_timeout());
|
||||
assert_eq!(err.url().map(|u| u.as_str()), Some(url.as_str()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get() {
|
||||
#[tokio::test]
|
||||
async fn response_timeout() {
|
||||
let _ = env_logger::try_init();
|
||||
|
||||
let server = server! {
|
||||
request: b"\
|
||||
GET /1 HTTP/1.1\r\n\
|
||||
GET /slow HTTP/1.1\r\n\
|
||||
user-agent: $USERAGENT\r\n\
|
||||
accept: */*\r\n\
|
||||
accept-encoding: gzip\r\n\
|
||||
@@ -151,362 +207,119 @@ fn test_get() {
|
||||
",
|
||||
response: b"\
|
||||
HTTP/1.1 200 OK\r\n\
|
||||
Server: test\r\n\
|
||||
Content-Length: 0\r\n\
|
||||
\r\n\
|
||||
"
|
||||
};
|
||||
|
||||
let url = format!("http://{}/1", server.addr());
|
||||
let mut res = reqwest::get(&url).unwrap();
|
||||
|
||||
assert_eq!(res.url().as_str(), &url);
|
||||
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||
assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test");
|
||||
assert_eq!(
|
||||
res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(),
|
||||
&"0"
|
||||
);
|
||||
assert_eq!(res.remote_addr(), Some(server.addr()));
|
||||
|
||||
assert_eq!(res.text().unwrap().len(), 0)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_post() {
|
||||
let server = server! {
|
||||
request: b"\
|
||||
POST /2 HTTP/1.1\r\n\
|
||||
content-length: 5\r\n\
|
||||
user-agent: $USERAGENT\r\n\
|
||||
accept: */*\r\n\
|
||||
accept-encoding: gzip\r\n\
|
||||
host: $HOST\r\n\
|
||||
Content-Length: 5\r\n\
|
||||
\r\n\
|
||||
Hello\
|
||||
",
|
||||
write_timeout: Duration::from_secs(2)
|
||||
};
|
||||
|
||||
let client = Client::builder()
|
||||
.timeout(Duration::from_millis(500))
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let url = format!("http://{}/slow", server.addr());
|
||||
let res = client.get(&url).send().await.expect("Failed to get");
|
||||
let body: Result<_, _> = res.into_body().try_concat().await;
|
||||
|
||||
let err = body.unwrap_err();
|
||||
|
||||
assert!(err.is_timeout());
|
||||
}
|
||||
|
||||
async fn gzip_case(response_size: usize, chunk_size: usize) {
|
||||
let content: String = (0..response_size)
|
||||
.into_iter()
|
||||
.map(|i| format!("test {}", i))
|
||||
.collect();
|
||||
let mut encoder = libflate::gzip::Encoder::new(Vec::new()).unwrap();
|
||||
match encoder.write(content.as_bytes()) {
|
||||
Ok(n) => assert!(n > 0, "Failed to write to encoder."),
|
||||
_ => panic!("Failed to gzip encode string."),
|
||||
};
|
||||
|
||||
let gzipped_content = encoder.finish().into_result().unwrap();
|
||||
|
||||
let mut response = format!(
|
||||
"\
|
||||
HTTP/1.1 200 OK\r\n\
|
||||
Server: test-accept\r\n\
|
||||
Content-Encoding: gzip\r\n\
|
||||
Content-Length: {}\r\n\
|
||||
\r\n",
|
||||
&gzipped_content.len()
|
||||
)
|
||||
.into_bytes();
|
||||
response.extend(&gzipped_content);
|
||||
|
||||
let server = server! {
|
||||
request: b"\
|
||||
GET /gzip HTTP/1.1\r\n\
|
||||
user-agent: $USERAGENT\r\n\
|
||||
accept: */*\r\n\
|
||||
accept-encoding: gzip\r\n\
|
||||
host: $HOST\r\n\
|
||||
\r\n\
|
||||
",
|
||||
chunk_size: chunk_size,
|
||||
write_timeout: Duration::from_millis(10),
|
||||
response: response
|
||||
};
|
||||
|
||||
let client = Client::new();
|
||||
|
||||
let mut res = client
|
||||
.get(&format!("http://{}/gzip", server.addr()))
|
||||
.send()
|
||||
.await
|
||||
.expect("response");
|
||||
|
||||
let body = res.text().await.expect("text");
|
||||
assert_eq!(body, content);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn body_stream() {
|
||||
let _ = env_logger::try_init();
|
||||
|
||||
let source = futures::stream::iter::<Vec<Result<Bytes, std::io::Error>>>(vec![
|
||||
Ok(Bytes::from_static(b"123")),
|
||||
Ok(Bytes::from_static(b"4567")),
|
||||
]);
|
||||
|
||||
let expected_body = "3\r\n123\r\n4\r\n4567\r\n0\r\n\r\n";
|
||||
|
||||
let server = server! {
|
||||
request: format!("\
|
||||
POST /post HTTP/1.1\r\n\
|
||||
user-agent: $USERAGENT\r\n\
|
||||
accept: */*\r\n\
|
||||
accept-encoding: gzip\r\n\
|
||||
host: $HOST\r\n\
|
||||
transfer-encoding: chunked\r\n\
|
||||
\r\n\
|
||||
{}\
|
||||
", expected_body),
|
||||
response: b"\
|
||||
HTTP/1.1 200 OK\r\n\
|
||||
Server: post\r\n\
|
||||
Content-Length: 0\r\n\
|
||||
Content-Length: 7\r\n\
|
||||
\r\n\
|
||||
"
|
||||
};
|
||||
|
||||
let url = format!("http://{}/2", server.addr());
|
||||
let mut res = reqwest::Client::new()
|
||||
let url = format!("http://{}/post", server.addr());
|
||||
|
||||
let client = Client::new();
|
||||
|
||||
let res = client
|
||||
.post(&url)
|
||||
.body("Hello")
|
||||
.body(Body::wrap_stream(source))
|
||||
.send()
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(res.url().as_str(), &url);
|
||||
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||
assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"post");
|
||||
assert_eq!(
|
||||
res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(),
|
||||
&"0"
|
||||
);
|
||||
|
||||
assert_eq!(res.text().unwrap().len(), 0)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_post_form() {
|
||||
let server = server! {
|
||||
request: b"\
|
||||
POST /form HTTP/1.1\r\n\
|
||||
content-type: application/x-www-form-urlencoded\r\n\
|
||||
content-length: 24\r\n\
|
||||
user-agent: $USERAGENT\r\n\
|
||||
accept: */*\r\n\
|
||||
accept-encoding: gzip\r\n\
|
||||
host: $HOST\r\n\
|
||||
\r\n\
|
||||
hello=world&sean=monstar\
|
||||
",
|
||||
response: b"\
|
||||
HTTP/1.1 200 OK\r\n\
|
||||
Server: post-form\r\n\
|
||||
Content-Length: 0\r\n\
|
||||
\r\n\
|
||||
"
|
||||
};
|
||||
|
||||
let form = &[("hello", "world"), ("sean", "monstar")];
|
||||
|
||||
let url = format!("http://{}/form", server.addr());
|
||||
let res = reqwest::Client::new()
|
||||
.post(&url)
|
||||
.form(form)
|
||||
.send()
|
||||
.expect("request send");
|
||||
.await
|
||||
.expect("Failed to post");
|
||||
|
||||
assert_eq!(res.url().as_str(), &url);
|
||||
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||
}
|
||||
|
||||
/// Calling `Response::error_for_status`` on a response with status in 4xx
|
||||
/// returns a error.
|
||||
#[test]
|
||||
fn test_error_for_status_4xx() {
|
||||
let server = server! {
|
||||
request: b"\
|
||||
GET /1 HTTP/1.1\r\n\
|
||||
user-agent: $USERAGENT\r\n\
|
||||
accept: */*\r\n\
|
||||
accept-encoding: gzip\r\n\
|
||||
host: $HOST\r\n\
|
||||
\r\n\
|
||||
",
|
||||
response: b"\
|
||||
HTTP/1.1 400 OK\r\n\
|
||||
Server: test\r\n\
|
||||
Content-Length: 0\r\n\
|
||||
\r\n\
|
||||
"
|
||||
};
|
||||
|
||||
let url = format!("http://{}/1", server.addr());
|
||||
let res = reqwest::get(&url).unwrap();
|
||||
|
||||
let err = res.error_for_status().err().unwrap();
|
||||
assert!(err.is_client_error());
|
||||
assert_eq!(err.status(), Some(reqwest::StatusCode::BAD_REQUEST));
|
||||
}
|
||||
|
||||
/// Calling `Response::error_for_status`` on a response with status in 5xx
|
||||
/// returns a error.
|
||||
#[test]
|
||||
fn test_error_for_status_5xx() {
|
||||
let server = server! {
|
||||
request: b"\
|
||||
GET /1 HTTP/1.1\r\n\
|
||||
user-agent: $USERAGENT\r\n\
|
||||
accept: */*\r\n\
|
||||
accept-encoding: gzip\r\n\
|
||||
host: $HOST\r\n\
|
||||
\r\n\
|
||||
",
|
||||
response: b"\
|
||||
HTTP/1.1 500 OK\r\n\
|
||||
Server: test\r\n\
|
||||
Content-Length: 0\r\n\
|
||||
\r\n\
|
||||
"
|
||||
};
|
||||
|
||||
let url = format!("http://{}/1", server.addr());
|
||||
let res = reqwest::get(&url).unwrap();
|
||||
|
||||
let err = res.error_for_status().err().unwrap();
|
||||
assert!(err.is_server_error());
|
||||
assert_eq!(
|
||||
err.status(),
|
||||
Some(reqwest::StatusCode::INTERNAL_SERVER_ERROR)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_default_headers() {
|
||||
use reqwest::header;
|
||||
let mut headers = header::HeaderMap::with_capacity(1);
|
||||
headers.insert(header::COOKIE, header::HeaderValue::from_static("a=b;c=d"));
|
||||
let client = reqwest::Client::builder()
|
||||
.default_headers(headers)
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let server = server! {
|
||||
request: b"\
|
||||
GET /1 HTTP/1.1\r\n\
|
||||
user-agent: $USERAGENT\r\n\
|
||||
accept: */*\r\n\
|
||||
cookie: a=b;c=d\r\n\
|
||||
accept-encoding: gzip\r\n\
|
||||
host: $HOST\r\n\
|
||||
\r\n\
|
||||
",
|
||||
response: b"\
|
||||
HTTP/1.1 200 OK\r\n\
|
||||
Server: test\r\n\
|
||||
Content-Length: 0\r\n\
|
||||
\r\n\
|
||||
"
|
||||
};
|
||||
|
||||
let url = format!("http://{}/1", server.addr());
|
||||
let res = client.get(&url).send().unwrap();
|
||||
|
||||
assert_eq!(res.url().as_str(), &url);
|
||||
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||
assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test");
|
||||
assert_eq!(
|
||||
res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(),
|
||||
&"0"
|
||||
);
|
||||
|
||||
let server = server! {
|
||||
request: b"\
|
||||
GET /2 HTTP/1.1\r\n\
|
||||
user-agent: $USERAGENT\r\n\
|
||||
accept: */*\r\n\
|
||||
cookie: a=b;c=d\r\n\
|
||||
accept-encoding: gzip\r\n\
|
||||
host: $HOST\r\n\
|
||||
\r\n\
|
||||
",
|
||||
response: b"\
|
||||
HTTP/1.1 200 OK\r\n\
|
||||
Server: test\r\n\
|
||||
Content-Length: 0\r\n\
|
||||
\r\n\
|
||||
"
|
||||
};
|
||||
|
||||
let url = format!("http://{}/2", server.addr());
|
||||
let res = client.get(&url).send().unwrap();
|
||||
|
||||
assert_eq!(res.url().as_str(), &url);
|
||||
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||
assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test");
|
||||
assert_eq!(
|
||||
res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(),
|
||||
&"0"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_override_default_headers() {
|
||||
use reqwest::header;
|
||||
let mut headers = header::HeaderMap::with_capacity(1);
|
||||
headers.insert(
|
||||
header::AUTHORIZATION,
|
||||
header::HeaderValue::from_static("iamatoken"),
|
||||
);
|
||||
let client = reqwest::Client::builder()
|
||||
.default_headers(headers)
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let server = server! {
|
||||
request: b"\
|
||||
GET /3 HTTP/1.1\r\n\
|
||||
authorization: secret\r\n\
|
||||
user-agent: $USERAGENT\r\n\
|
||||
accept: */*\r\n\
|
||||
accept-encoding: gzip\r\n\
|
||||
host: $HOST\r\n\
|
||||
\r\n\
|
||||
",
|
||||
response: b"\
|
||||
HTTP/1.1 200 OK\r\n\
|
||||
Server: test\r\n\
|
||||
Content-Length: 0\r\n\
|
||||
\r\n\
|
||||
"
|
||||
};
|
||||
|
||||
let url = format!("http://{}/3", server.addr());
|
||||
let res = client
|
||||
.get(&url)
|
||||
.header(
|
||||
header::AUTHORIZATION,
|
||||
header::HeaderValue::from_static("secret"),
|
||||
)
|
||||
.send()
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(res.url().as_str(), &url);
|
||||
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||
assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test");
|
||||
assert_eq!(
|
||||
res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(),
|
||||
&"0"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_appended_headers_not_overwritten() {
|
||||
let client = reqwest::Client::new();
|
||||
|
||||
let server = server! {
|
||||
request: b"\
|
||||
GET /4 HTTP/1.1\r\n\
|
||||
accept: application/json\r\n\
|
||||
accept: application/json+hal\r\n\
|
||||
user-agent: $USERAGENT\r\n\
|
||||
accept-encoding: gzip\r\n\
|
||||
host: $HOST\r\n\
|
||||
\r\n\
|
||||
",
|
||||
response: b"\
|
||||
HTTP/1.1 200 OK\r\n\
|
||||
Server: test\r\n\
|
||||
Content-Length: 0\r\n\
|
||||
\r\n\
|
||||
"
|
||||
};
|
||||
|
||||
let url = format!("http://{}/4", server.addr());
|
||||
let res = client
|
||||
.get(&url)
|
||||
.header(header::ACCEPT, "application/json")
|
||||
.header(header::ACCEPT, "application/json+hal")
|
||||
.send()
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(res.url().as_str(), &url);
|
||||
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||
assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test");
|
||||
assert_eq!(
|
||||
res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(),
|
||||
&"0"
|
||||
);
|
||||
|
||||
// make sure this also works with default headers
|
||||
use reqwest::header;
|
||||
let mut headers = header::HeaderMap::with_capacity(1);
|
||||
headers.insert(
|
||||
header::ACCEPT,
|
||||
header::HeaderValue::from_static("text/html"),
|
||||
);
|
||||
let client = reqwest::Client::builder()
|
||||
.default_headers(headers)
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
let server = server! {
|
||||
request: b"\
|
||||
GET /4 HTTP/1.1\r\n\
|
||||
accept: application/json\r\n\
|
||||
accept: application/json+hal\r\n\
|
||||
user-agent: $USERAGENT\r\n\
|
||||
accept-encoding: gzip\r\n\
|
||||
host: $HOST\r\n\
|
||||
\r\n\
|
||||
",
|
||||
response: b"\
|
||||
HTTP/1.1 200 OK\r\n\
|
||||
Server: test\r\n\
|
||||
Content-Length: 0\r\n\
|
||||
\r\n\
|
||||
"
|
||||
};
|
||||
|
||||
let url = format!("http://{}/4", server.addr());
|
||||
let res = client
|
||||
.get(&url)
|
||||
.header(header::ACCEPT, "application/json")
|
||||
.header(header::ACCEPT, "application/json+hal")
|
||||
.send()
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(res.url().as_str(), &url);
|
||||
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||
assert_eq!(res.headers().get(reqwest::header::SERVER).unwrap(), &"test");
|
||||
assert_eq!(
|
||||
res.headers().get(reqwest::header::CONTENT_LENGTH).unwrap(),
|
||||
&"0"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ fn test_gzip_response() {
|
||||
write_timeout: Duration::from_millis(10),
|
||||
response: response
|
||||
};
|
||||
let mut res = reqwest::get(&format!("http://{}/gzip", server.addr())).unwrap();
|
||||
let mut res = reqwest::blocking::get(&format!("http://{}/gzip", server.addr())).unwrap();
|
||||
|
||||
let mut body = String::new();
|
||||
res.read_to_string(&mut body).unwrap();
|
||||
@@ -68,7 +68,7 @@ fn test_gzip_empty_body() {
|
||||
\r\n"
|
||||
};
|
||||
|
||||
let client = reqwest::Client::new();
|
||||
let client = reqwest::blocking::Client::new();
|
||||
let mut res = client
|
||||
.head(&format!("http://{}/gzip", server.addr()))
|
||||
.send()
|
||||
@@ -100,7 +100,7 @@ fn test_gzip_invalid_body() {
|
||||
0"
|
||||
};
|
||||
|
||||
let mut res = reqwest::get(&format!("http://{}/gzip", server.addr())).unwrap();
|
||||
let mut res = reqwest::blocking::get(&format!("http://{}/gzip", server.addr())).unwrap();
|
||||
// this tests that the request.send() didn't error, but that the error
|
||||
// is in reading the body
|
||||
|
||||
@@ -126,7 +126,7 @@ fn test_accept_header_is_not_changed_if_set() {
|
||||
\r\n\
|
||||
"
|
||||
};
|
||||
let client = reqwest::Client::new();
|
||||
let client = reqwest::blocking::Client::new();
|
||||
|
||||
let res = client
|
||||
.get(&format!("http://{}/accept", server.addr()))
|
||||
@@ -158,7 +158,7 @@ fn test_accept_encoding_header_is_not_changed_if_set() {
|
||||
\r\n\
|
||||
"
|
||||
};
|
||||
let client = reqwest::Client::new();
|
||||
let client = reqwest::blocking::Client::new();
|
||||
|
||||
let res = client
|
||||
.get(&format!("http://{}/accept-encoding", server.addr()))
|
||||
|
||||
@@ -5,7 +5,7 @@ mod support;
|
||||
fn text_part() {
|
||||
let _ = env_logger::try_init();
|
||||
|
||||
let form = reqwest::multipart::Form::new().text("foo", "bar");
|
||||
let form = reqwest::blocking::multipart::Form::new().text("foo", "bar");
|
||||
|
||||
let expected_body = format!(
|
||||
"\
|
||||
@@ -39,7 +39,7 @@ fn text_part() {
|
||||
|
||||
let url = format!("http://{}/multipart/1", server.addr());
|
||||
|
||||
let res = reqwest::Client::new()
|
||||
let res = reqwest::blocking::Client::new()
|
||||
.post(&url)
|
||||
.multipart(form)
|
||||
.send()
|
||||
@@ -53,7 +53,7 @@ fn text_part() {
|
||||
fn file() {
|
||||
let _ = env_logger::try_init();
|
||||
|
||||
let form = reqwest::multipart::Form::new()
|
||||
let form = reqwest::blocking::multipart::Form::new()
|
||||
.file("foo", "Cargo.lock")
|
||||
.unwrap();
|
||||
|
||||
@@ -93,7 +93,7 @@ fn file() {
|
||||
|
||||
let url = format!("http://{}/multipart/2", server.addr());
|
||||
|
||||
let res = reqwest::Client::new()
|
||||
let res = reqwest::blocking::Client::new()
|
||||
.post(&url)
|
||||
.multipart(form)
|
||||
.send()
|
||||
|
||||
@@ -3,8 +3,8 @@ mod support;
|
||||
|
||||
use std::env;
|
||||
|
||||
#[test]
|
||||
fn http_proxy() {
|
||||
#[tokio::test]
|
||||
async fn http_proxy() {
|
||||
let server = server! {
|
||||
request: b"\
|
||||
GET http://hyper.rs/prox HTTP/1.1\r\n\
|
||||
@@ -31,6 +31,7 @@ fn http_proxy() {
|
||||
.unwrap()
|
||||
.get(url)
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(res.url().as_str(), url);
|
||||
@@ -41,8 +42,8 @@ fn http_proxy() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn http_proxy_basic_auth() {
|
||||
#[tokio::test]
|
||||
async fn http_proxy_basic_auth() {
|
||||
let server = server! {
|
||||
request: b"\
|
||||
GET http://hyper.rs/prox HTTP/1.1\r\n\
|
||||
@@ -74,6 +75,7 @@ fn http_proxy_basic_auth() {
|
||||
.unwrap()
|
||||
.get(url)
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(res.url().as_str(), url);
|
||||
@@ -84,8 +86,8 @@ fn http_proxy_basic_auth() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn http_proxy_basic_auth_parsed() {
|
||||
#[tokio::test]
|
||||
async fn http_proxy_basic_auth_parsed() {
|
||||
let server = server! {
|
||||
request: b"\
|
||||
GET http://hyper.rs/prox HTTP/1.1\r\n\
|
||||
@@ -113,6 +115,7 @@ fn http_proxy_basic_auth_parsed() {
|
||||
.unwrap()
|
||||
.get(url)
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(res.url().as_str(), url);
|
||||
@@ -123,8 +126,8 @@ fn http_proxy_basic_auth_parsed() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_no_proxy() {
|
||||
#[tokio::test]
|
||||
async fn test_no_proxy() {
|
||||
let server = server! {
|
||||
request: b"\
|
||||
GET /4 HTTP/1.1\r\n\
|
||||
@@ -152,14 +155,15 @@ fn test_no_proxy() {
|
||||
.unwrap()
|
||||
.get(&url)
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(res.url().as_str(), &url);
|
||||
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_using_system_proxy() {
|
||||
#[tokio::test]
|
||||
async fn test_using_system_proxy() {
|
||||
let server = server! {
|
||||
request: b"\
|
||||
GET http://hyper.rs/prox HTTP/1.1\r\n\
|
||||
@@ -188,6 +192,7 @@ fn test_using_system_proxy() {
|
||||
.unwrap()
|
||||
.get(url)
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(res.url().as_str(), url);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#[macro_use]
|
||||
mod support;
|
||||
|
||||
#[test]
|
||||
fn test_redirect_301_and_302_and_303_changes_post_to_get() {
|
||||
#[tokio::test]
|
||||
async fn test_redirect_301_and_302_and_303_changes_post_to_get() {
|
||||
let client = reqwest::Client::new();
|
||||
let codes = [301, 302, 303];
|
||||
|
||||
@@ -45,7 +45,7 @@ fn test_redirect_301_and_302_and_303_changes_post_to_get() {
|
||||
|
||||
let url = format!("http://{}/{}", redirect.addr(), code);
|
||||
let dst = format!("http://{}/{}", redirect.addr(), "dst");
|
||||
let res = client.post(&url).send().unwrap();
|
||||
let res = client.post(&url).send().await.unwrap();
|
||||
assert_eq!(res.url().as_str(), dst);
|
||||
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||
assert_eq!(
|
||||
@@ -55,8 +55,8 @@ fn test_redirect_301_and_302_and_303_changes_post_to_get() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_redirect_307_and_308_tries_to_get_again() {
|
||||
#[tokio::test]
|
||||
async fn test_redirect_307_and_308_tries_to_get_again() {
|
||||
let client = reqwest::Client::new();
|
||||
let codes = [307, 308];
|
||||
for code in codes.iter() {
|
||||
@@ -98,7 +98,7 @@ fn test_redirect_307_and_308_tries_to_get_again() {
|
||||
|
||||
let url = format!("http://{}/{}", redirect.addr(), code);
|
||||
let dst = format!("http://{}/{}", redirect.addr(), "dst");
|
||||
let res = client.get(&url).send().unwrap();
|
||||
let res = client.get(&url).send().await.unwrap();
|
||||
assert_eq!(res.url().as_str(), dst);
|
||||
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||
assert_eq!(
|
||||
@@ -108,19 +108,19 @@ fn test_redirect_307_and_308_tries_to_get_again() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_redirect_307_and_308_tries_to_post_again() {
|
||||
#[tokio::test]
|
||||
async fn test_redirect_307_and_308_tries_to_post_again() {
|
||||
let client = reqwest::Client::new();
|
||||
let codes = [307, 308];
|
||||
for code in codes.iter() {
|
||||
let redirect = server! {
|
||||
request: format!("\
|
||||
POST /{} HTTP/1.1\r\n\
|
||||
content-length: 5\r\n\
|
||||
user-agent: $USERAGENT\r\n\
|
||||
accept: */*\r\n\
|
||||
accept-encoding: gzip\r\n\
|
||||
host: $HOST\r\n\
|
||||
content-length: 5\r\n\
|
||||
\r\n\
|
||||
Hello\
|
||||
", code),
|
||||
@@ -136,12 +136,12 @@ fn test_redirect_307_and_308_tries_to_post_again() {
|
||||
|
||||
request: format!("\
|
||||
POST /dst HTTP/1.1\r\n\
|
||||
content-length: 5\r\n\
|
||||
user-agent: $USERAGENT\r\n\
|
||||
accept: */*\r\n\
|
||||
accept-encoding: gzip\r\n\
|
||||
referer: http://$HOST/{}\r\n\
|
||||
host: $HOST\r\n\
|
||||
content-length: 5\r\n\
|
||||
\r\n\
|
||||
Hello\
|
||||
", code),
|
||||
@@ -155,7 +155,7 @@ fn test_redirect_307_and_308_tries_to_post_again() {
|
||||
|
||||
let url = format!("http://{}/{}", redirect.addr(), code);
|
||||
let dst = format!("http://{}/{}", redirect.addr(), "dst");
|
||||
let res = client.post(&url).body("Hello").send().unwrap();
|
||||
let res = client.post(&url).body("Hello").send().await.unwrap();
|
||||
assert_eq!(res.url().as_str(), dst);
|
||||
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||
assert_eq!(
|
||||
@@ -167,7 +167,7 @@ fn test_redirect_307_and_308_tries_to_post_again() {
|
||||
|
||||
#[test]
|
||||
fn test_redirect_307_does_not_try_if_reader_cannot_reset() {
|
||||
let client = reqwest::Client::new();
|
||||
let client = reqwest::blocking::Client::new();
|
||||
let codes = [307, 308];
|
||||
for &code in codes.iter() {
|
||||
let redirect = server! {
|
||||
@@ -196,7 +196,7 @@ fn test_redirect_307_does_not_try_if_reader_cannot_reset() {
|
||||
let url = format!("http://{}/{}", redirect.addr(), code);
|
||||
let res = client
|
||||
.post(&url)
|
||||
.body(reqwest::Body::new(&b"Hello"[..]))
|
||||
.body(reqwest::blocking::Body::new(&b"Hello"[..]))
|
||||
.send()
|
||||
.unwrap();
|
||||
assert_eq!(res.url().as_str(), url);
|
||||
@@ -204,8 +204,8 @@ fn test_redirect_307_does_not_try_if_reader_cannot_reset() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_redirect_removes_sensitive_headers() {
|
||||
#[tokio::test]
|
||||
async fn test_redirect_removes_sensitive_headers() {
|
||||
let end_server = server! {
|
||||
request: b"\
|
||||
GET /otherhost HTTP/1.1\r\n\
|
||||
@@ -252,11 +252,12 @@ fn test_redirect_removes_sensitive_headers() {
|
||||
reqwest::header::HeaderValue::from_static("foo=bar"),
|
||||
)
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_redirect_policy_can_return_errors() {
|
||||
#[tokio::test]
|
||||
async fn test_redirect_policy_can_return_errors() {
|
||||
let server = server! {
|
||||
request: b"\
|
||||
GET /loop HTTP/1.1\r\n\
|
||||
@@ -274,13 +275,13 @@ fn test_redirect_policy_can_return_errors() {
|
||||
\r\n\
|
||||
"
|
||||
};
|
||||
|
||||
let err = reqwest::get(&format!("http://{}/loop", server.addr())).unwrap_err();
|
||||
let url = format!("http://{}/loop", server.addr());
|
||||
let err = reqwest::get(&url).await.unwrap_err();
|
||||
assert!(err.is_redirect());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_redirect_policy_can_stop_redirects_without_an_error() {
|
||||
#[tokio::test]
|
||||
async fn test_redirect_policy_can_stop_redirects_without_an_error() {
|
||||
let server = server! {
|
||||
request: b"\
|
||||
GET /no-redirect HTTP/1.1\r\n\
|
||||
@@ -307,6 +308,7 @@ fn test_redirect_policy_can_stop_redirects_without_an_error() {
|
||||
.unwrap()
|
||||
.get(&url)
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(res.url().as_str(), url);
|
||||
@@ -317,8 +319,8 @@ fn test_redirect_policy_can_stop_redirects_without_an_error() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_referer_is_not_set_if_disabled() {
|
||||
#[tokio::test]
|
||||
async fn test_referer_is_not_set_if_disabled() {
|
||||
let server = server! {
|
||||
request: b"\
|
||||
GET /no-refer HTTP/1.1\r\n\
|
||||
@@ -357,14 +359,14 @@ fn test_referer_is_not_set_if_disabled() {
|
||||
.referer(false)
|
||||
.build()
|
||||
.unwrap()
|
||||
//client
|
||||
.get(&format!("http://{}/no-refer", server.addr()))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_invalid_location_stops_redirect_gh484() {
|
||||
#[tokio::test]
|
||||
async fn test_invalid_location_stops_redirect_gh484() {
|
||||
let server = server! {
|
||||
request: b"\
|
||||
GET /yikes HTTP/1.1\r\n\
|
||||
@@ -385,7 +387,7 @@ fn test_invalid_location_stops_redirect_gh484() {
|
||||
|
||||
let url = format!("http://{}/yikes", server.addr());
|
||||
|
||||
let res = reqwest::get(&url).unwrap();
|
||||
let res = reqwest::get(&url).await.unwrap();
|
||||
|
||||
assert_eq!(res.url().as_str(), url);
|
||||
assert_eq!(res.status(), reqwest::StatusCode::FOUND);
|
||||
@@ -395,8 +397,8 @@ fn test_invalid_location_stops_redirect_gh484() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_redirect_302_with_set_cookies() {
|
||||
#[tokio::test]
|
||||
async fn test_redirect_302_with_set_cookies() {
|
||||
let code = 302;
|
||||
let client = reqwest::ClientBuilder::new()
|
||||
.cookie_store(true)
|
||||
@@ -442,7 +444,7 @@ fn test_redirect_302_with_set_cookies() {
|
||||
|
||||
let url = format!("http://{}/{}", server.addr(), code);
|
||||
let dst = format!("http://{}/{}", server.addr(), "dst");
|
||||
let res = client.get(&url).send().unwrap();
|
||||
let res = client.get(&url).send().await.unwrap();
|
||||
|
||||
assert_eq!(res.url().as_str(), dst);
|
||||
assert_eq!(res.status(), reqwest::StatusCode::OK);
|
||||
|
||||
@@ -11,7 +11,7 @@ fn timeout_closes_connection() {
|
||||
|
||||
// Make Client drop *after* the Server, so the background doesn't
|
||||
// close too early.
|
||||
let client = reqwest::Client::builder()
|
||||
let client = reqwest::blocking::Client::builder()
|
||||
.timeout(Duration::from_millis(500))
|
||||
.build()
|
||||
.unwrap();
|
||||
@@ -50,7 +50,7 @@ fn write_timeout_large_body() {
|
||||
|
||||
// Make Client drop *after* the Server, so the background doesn't
|
||||
// close too early.
|
||||
let client = reqwest::Client::builder()
|
||||
let client = reqwest::blocking::Client::builder()
|
||||
.timeout(Duration::from_millis(500))
|
||||
.build()
|
||||
.unwrap();
|
||||
@@ -80,7 +80,7 @@ fn write_timeout_large_body() {
|
||||
let url = format!("http://{}/write-timeout", server.addr());
|
||||
let err = client
|
||||
.post(&url)
|
||||
.body(reqwest::Body::sized(cursor, len as u64))
|
||||
.body(reqwest::blocking::Body::sized(cursor, len as u64))
|
||||
.send()
|
||||
.unwrap_err();
|
||||
|
||||
@@ -108,7 +108,7 @@ fn test_response_timeout() {
|
||||
};
|
||||
|
||||
let url = format!("http://{}/response-timeout", server.addr());
|
||||
let err = reqwest::Client::builder()
|
||||
let err = reqwest::blocking::Client::builder()
|
||||
.timeout(Duration::from_millis(500))
|
||||
.build()
|
||||
.unwrap()
|
||||
@@ -142,7 +142,7 @@ fn test_read_timeout() {
|
||||
};
|
||||
|
||||
let url = format!("http://{}/read-timeout", server.addr());
|
||||
let mut res = reqwest::Client::builder()
|
||||
let mut res = reqwest::blocking::Client::builder()
|
||||
.timeout(Duration::from_millis(500))
|
||||
.build()
|
||||
.unwrap()
|
||||
|
||||
Reference in New Issue
Block a user