Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add post_async example usage #273

Merged
merged 7 commits into from
Dec 15, 2020
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
target
Cargo.lock
*.code-workspace
.idea/*

# Code coverage reports
cobertura.xml
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ structopt = "0.3"
tempfile = "3.1"
test-case = "1.0"
tracing-subscriber = "=0.2.12"
async-std = "1.8.0"
serde_json = "1"
tokio = { version = "0.3", features = ["full"] }
baoyachi marked this conversation as resolved.
Show resolved Hide resolved

[dev-dependencies.testserver]
path = "testserver"
Expand Down
5 changes: 1 addition & 4 deletions examples/client.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
//! Another simple example that creates a custom HTTP client instance and sends
//! a GET request with it instead of using the default client.

use isahc::{
config::RedirectPolicy,
prelude::*,
};
use isahc::{config::RedirectPolicy, prelude::*};
use std::{
io::{copy, stdout},
time::Duration,
Expand Down
5 changes: 1 addition & 4 deletions examples/http2.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
//! This example simply demonstrates HTTP/2 support by making a request that
//! enforces usage of HTTP/2.

use isahc::{
config::VersionNegotiation,
prelude::*,
};
use isahc::{config::VersionNegotiation, prelude::*};

fn main() -> Result<(), isahc::Error> {
let response = Request::get("https://nghttp2.org")
Expand Down
2 changes: 1 addition & 1 deletion src/body/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ impl Body {
#[inline]
pub fn from_bytes_static<B>(bytes: B) -> Self
where
B: AsRef<[u8]> + 'static
B: AsRef<[u8]> + 'static,
{
match_type! {
<bytes as Cursor<Cow<'static, [u8]>>> => Self(Inner::Buffer(bytes)),
Expand Down
59 changes: 32 additions & 27 deletions src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -921,27 +921,28 @@ impl HttpClient {
async_body
});

let response = block_on(async move {
// Instead of simply blocking the current thread until the response
// is received, we can use the current thread to read from the
// request body synchronously while concurrently waiting for the
// response.
if let Some(mut writer) = writer_maybe {
// Note that the `send_async` future is given first; this
// ensures that it is polled first and thus the request is
// initiated before we attempt to write the request body.
let (response, _) = try_zip(
self.send_async_inner(request),
async move {
let response = block_on(
async move {
// Instead of simply blocking the current thread until the response
// is received, we can use the current thread to read from the
// request body synchronously while concurrently waiting for the
// response.
if let Some(mut writer) = writer_maybe {
// Note that the `send_async` future is given first; this
// ensures that it is polled first and thus the request is
// initiated before we attempt to write the request body.
let (response, _) = try_zip(self.send_async_inner(request), async move {
writer.write().await.map_err(Error::from)
},
).await?;
})
.await?;

Ok(response)
} else {
self.send_async_inner(request).await
Ok(response)
} else {
self.send_async_inner(request).await
}
}
}.instrument(span))?;
.instrument(span),
)?;

Ok(response.map(|body| body.into_sync()))
}
Expand Down Expand Up @@ -980,11 +981,17 @@ impl HttpClient {
uri = ?request.uri(),
);

ResponseFuture::new(self.send_async_inner(request.map(Into::into)).instrument(span))
ResponseFuture::new(
self.send_async_inner(request.map(Into::into))
.instrument(span),
)
}

/// Actually send the request. All the public methods go through here.
async fn send_async_inner(&self, mut request: Request<AsyncBody>) -> Result<Response<AsyncBody>, Error> {
async fn send_async_inner(
&self,
mut request: Request<AsyncBody>,
) -> Result<Response<AsyncBody>, Error> {
// Set redirect policy if not specified.
if request.extensions().get::<RedirectPolicy>().is_none() {
if let Some(policy) = self.inner.defaults.get::<RedirectPolicy>().cloned() {
Expand Down Expand Up @@ -1162,7 +1169,9 @@ impl crate::interceptor::Invoke for &HttpClient {

// Check if automatic decompression is enabled; we'll need to know
// this later after the response is sent.
let is_automatic_decompression = request.extensions().get()
let is_automatic_decompression = request
.extensions()
.get()
.or_else(|| self.inner.defaults.get())
.map(|AutomaticDecompression(enabled)| *enabled)
.unwrap_or(false);
Expand Down Expand Up @@ -1223,9 +1232,7 @@ impl fmt::Debug for HttpClient {

/// A future for a request being executed.
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub struct ResponseFuture<'c>(
Pin<Box<dyn Future<Output = <Self as Future>::Output> + 'c + Send>>,
);
pub struct ResponseFuture<'c>(Pin<Box<dyn Future<Output = <Self as Future>::Output> + 'c + Send>>);

impl<'c> ResponseFuture<'c> {
fn new<F>(future: F) -> Self
Expand All @@ -1236,9 +1243,7 @@ impl<'c> ResponseFuture<'c> {
}

fn error(error: Error) -> Self {
Self::new(async move {
Err(error)
})
Self::new(async move { Err(error) })
}
}

Expand Down
7 changes: 1 addition & 6 deletions src/config/dial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,7 @@
use super::SetOpt;
use curl::easy::{Easy2, List};
use http::Uri;
use std::{
convert::TryFrom,
fmt,
net::SocketAddr,
str::FromStr,
};
use std::{convert::TryFrom, fmt, net::SocketAddr, str::FromStr};

/// An error which can be returned when parsing a dial address.
#[derive(Clone, Debug, Eq, PartialEq)]
Expand Down
5 changes: 1 addition & 4 deletions src/config/dns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@

use super::SetOpt;
use curl::easy::Easy2;
use std::{
net::IpAddr,
time::Duration,
};
use std::{net::IpAddr, time::Duration};

/// DNS caching configuration.
///
Expand Down
6 changes: 1 addition & 5 deletions src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,7 @@
use self::internal::SetOpt;
use crate::auth::{Authentication, Credentials};
use curl::easy::Easy2;
use std::{
iter::FromIterator,
net::IpAddr,
time::Duration,
};
use std::{iter::FromIterator, net::IpAddr, time::Duration};

pub(crate) mod dial;
pub(crate) mod dns;
Expand Down
16 changes: 5 additions & 11 deletions src/cookies/cookie.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
use chrono::{prelude::*, Duration};
use std::{
error::Error,
fmt,
str,
};
use std::{error::Error, fmt, str};

/// An error which can occur when attempting to parse a cookie string.
#[derive(Debug)]
Expand Down Expand Up @@ -246,12 +242,10 @@ fn parse_cookie_value(mut bytes: &[u8]) -> Result<&str, ParseError> {

// https://tools.ietf.org/html/rfc6265#section-4.1.1
fn is_valid_cookie_value(bytes: &[u8]) -> bool {
bytes
.iter()
.all(|&byte| match byte {
0x21 | 0x23..=0x2B | 0x2D..=0x3A | 0x3C..=0x5B | 0x5D..=0x7E => true,
_ => false,
})
bytes.iter().all(|&byte| match byte {
0x21 | 0x23..=0x2B | 0x2D..=0x3A | 0x3C..=0x5B | 0x5D..=0x7E => true,
_ => false,
})
}

// https://tools.ietf.org/html/rfc2616#section-2.2
Expand Down
30 changes: 18 additions & 12 deletions src/cookies/interceptor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,32 @@ pub(crate) struct CookieInterceptor {

impl CookieInterceptor {
pub(crate) fn new(cookie_jar: Option<CookieJar>) -> Self {
Self {
cookie_jar,
}
Self { cookie_jar }
}
}

impl Interceptor for CookieInterceptor {
type Err = Error;

fn intercept<'a>(&'a self, mut request: Request<AsyncBody>, ctx: Context<'a>) -> InterceptorFuture<'a, Self::Err> {
fn intercept<'a>(
&'a self,
mut request: Request<AsyncBody>,
ctx: Context<'a>,
) -> InterceptorFuture<'a, Self::Err> {
Box::pin(async move {
// Determine the cookie jar to use for this request. If one is
// attached to this specific request, use it, otherwise use the
// default one.
let jar = request.extensions().get::<CookieJar>()
let jar = request
.extensions()
.get::<CookieJar>()
.cloned()
.or_else(|| self.cookie_jar.clone());

if let Some(jar) = jar.as_ref() {
// Get the outgoing cookie header.
let mut cookie_string = request.headers_mut()
let mut cookie_string = request
.headers_mut()
.remove(http::header::COOKIE)
.map(|value| value.as_bytes().to_vec())
.unwrap_or_default();
Expand Down Expand Up @@ -70,8 +75,7 @@ impl Interceptor for CookieInterceptor {
if let Some(jar) = jar {
// Persist cookies returned from the server, if any.
if response.headers().contains_key(http::header::SET_COOKIE) {
let request_uri = response.effective_uri()
.unwrap_or(&request_uri);
let request_uri = response.effective_uri().unwrap_or(&request_uri);

let cookies = response
.headers()
Expand All @@ -83,10 +87,12 @@ impl Interceptor for CookieInterceptor {
None
})
})
.filter_map(|header| Cookie::parse(header).ok().or_else(|| {
tracing::warn!("could not parse Set-Cookie header");
None
}));
.filter_map(|header| {
Cookie::parse(header).ok().or_else(|| {
tracing::warn!("could not parse Set-Cookie header");
None
})
});

for cookie in cookies {
jar.set(cookie, request_uri);
Expand Down
3 changes: 2 additions & 1 deletion src/cookies/jar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ impl CookieJar {
pub fn get_for_uri(&self, uri: &Uri) -> impl IntoIterator<Item = Cookie> {
let jar = self.cookies.read().unwrap();

let mut cookies = jar.iter()
let mut cookies = jar
.iter()
.filter(|cookie| cookie.matches(uri))
.map(|c| c.cookie.clone())
.collect::<Vec<_>>();
Expand Down
7 changes: 2 additions & 5 deletions src/cookies/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,10 @@
//! feature is enabled.

mod cookie;
mod jar;
pub(crate) mod interceptor;
mod jar;

#[cfg(feature = "psl")]
mod psl;

pub use self::{
cookie::Cookie,
jar::CookieJar,
};
pub use self::{cookie::Cookie, jar::CookieJar};
5 changes: 1 addition & 4 deletions src/cookies/psl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,7 @@
//! since a stale list is better than no list at all.

use crate::request::RequestExt;
use chrono::{
prelude::*,
Duration,
};
use chrono::{prelude::*, Duration};
use once_cell::sync::Lazy;
use parking_lot::{RwLock, RwLockUpgradableReadGuard};
use publicsuffix::List;
Expand Down
6 changes: 3 additions & 3 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,9 +213,9 @@ impl Error {
/// Returns true if this error was likely the fault of the server.
pub fn is_server(&self) -> bool {
match self.kind() {
ErrorKind::BadServerCertificate | ErrorKind::ProtocolViolation | ErrorKind::TooManyRedirects => {
true
}
ErrorKind::BadServerCertificate
| ErrorKind::ProtocolViolation
| ErrorKind::TooManyRedirects => true,
_ => false,
}
}
Expand Down
Loading