Check format to all rs files under src (#1188)
fixed-format of all missing files. Fixes seanmonstar/reqwest#1186
This commit is contained in:
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
@@ -34,6 +34,10 @@ jobs:
|
|||||||
command: fmt
|
command: fmt
|
||||||
args: -- --check
|
args: -- --check
|
||||||
|
|
||||||
|
- name: temporary workaround - fmt all files under src
|
||||||
|
# Workaround for rust-lang/cargo#7732
|
||||||
|
run: cargo fmt -- --check $(find . -name '*.rs' -print)
|
||||||
|
|
||||||
build:
|
build:
|
||||||
name: ${{ matrix.name }}
|
name: ${{ matrix.name }}
|
||||||
needs: [style]
|
needs: [style]
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
#[cfg(any(
|
#[cfg(any(feature = "native-tls", feature = "__rustls",))]
|
||||||
feature = "native-tls",
|
|
||||||
feature = "__rustls",
|
|
||||||
))]
|
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::net::IpAddr;
|
use std::net::IpAddr;
|
||||||
@@ -21,13 +18,13 @@ use http::Uri;
|
|||||||
use hyper::client::ResponseFuture;
|
use hyper::client::ResponseFuture;
|
||||||
#[cfg(feature = "native-tls-crate")]
|
#[cfg(feature = "native-tls-crate")]
|
||||||
use native_tls_crate::TlsConnector;
|
use native_tls_crate::TlsConnector;
|
||||||
|
use pin_project_lite::pin_project;
|
||||||
#[cfg(feature = "rustls-tls-native-roots")]
|
#[cfg(feature = "rustls-tls-native-roots")]
|
||||||
use rustls::RootCertStore;
|
use rustls::RootCertStore;
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::task::{Context, Poll};
|
use std::task::{Context, Poll};
|
||||||
use tokio::time::Sleep;
|
use tokio::time::Sleep;
|
||||||
use pin_project_lite::pin_project;
|
|
||||||
|
|
||||||
use log::debug;
|
use log::debug;
|
||||||
|
|
||||||
@@ -232,7 +229,6 @@ impl ClientBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Connector::new_default_tls(
|
Connector::new_default_tls(
|
||||||
http,
|
http,
|
||||||
tls,
|
tls,
|
||||||
@@ -241,27 +237,25 @@ impl ClientBuilder {
|
|||||||
config.local_address,
|
config.local_address,
|
||||||
config.nodelay,
|
config.nodelay,
|
||||||
)?
|
)?
|
||||||
},
|
}
|
||||||
#[cfg(feature = "native-tls")]
|
#[cfg(feature = "native-tls")]
|
||||||
TlsBackend::BuiltNativeTls(conn) => {
|
TlsBackend::BuiltNativeTls(conn) => Connector::from_built_default_tls(
|
||||||
Connector::from_built_default_tls(
|
http,
|
||||||
http,
|
conn,
|
||||||
conn,
|
proxies.clone(),
|
||||||
proxies.clone(),
|
user_agent(&config.headers),
|
||||||
user_agent(&config.headers),
|
config.local_address,
|
||||||
config.local_address,
|
config.nodelay,
|
||||||
config.nodelay)
|
),
|
||||||
},
|
|
||||||
#[cfg(feature = "__rustls")]
|
#[cfg(feature = "__rustls")]
|
||||||
TlsBackend::BuiltRustls(conn) => {
|
TlsBackend::BuiltRustls(conn) => Connector::new_rustls_tls(
|
||||||
Connector::new_rustls_tls(
|
http,
|
||||||
http,
|
conn,
|
||||||
conn,
|
proxies.clone(),
|
||||||
proxies.clone(),
|
user_agent(&config.headers),
|
||||||
user_agent(&config.headers),
|
config.local_address,
|
||||||
config.local_address,
|
config.nodelay,
|
||||||
config.nodelay)
|
),
|
||||||
},
|
|
||||||
#[cfg(feature = "__rustls")]
|
#[cfg(feature = "__rustls")]
|
||||||
TlsBackend::Rustls => {
|
TlsBackend::Rustls => {
|
||||||
use crate::tls::NoVerifier;
|
use crate::tls::NoVerifier;
|
||||||
@@ -274,8 +268,8 @@ impl ClientBuilder {
|
|||||||
}
|
}
|
||||||
#[cfg(feature = "rustls-tls-webpki-roots")]
|
#[cfg(feature = "rustls-tls-webpki-roots")]
|
||||||
if config.tls_built_in_root_certs {
|
if config.tls_built_in_root_certs {
|
||||||
tls.root_store
|
tls.root_store
|
||||||
.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
|
.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
|
||||||
}
|
}
|
||||||
#[cfg(feature = "rustls-tls-native-roots")]
|
#[cfg(feature = "rustls-tls-native-roots")]
|
||||||
if config.tls_built_in_root_certs {
|
if config.tls_built_in_root_certs {
|
||||||
@@ -304,16 +298,13 @@ impl ClientBuilder {
|
|||||||
config.local_address,
|
config.local_address,
|
||||||
config.nodelay,
|
config.nodelay,
|
||||||
)
|
)
|
||||||
},
|
}
|
||||||
#[cfg(any(
|
#[cfg(any(feature = "native-tls", feature = "__rustls",))]
|
||||||
feature = "native-tls",
|
|
||||||
feature = "__rustls",
|
|
||||||
))]
|
|
||||||
TlsBackend::UnknownPreconfigured => {
|
TlsBackend::UnknownPreconfigured => {
|
||||||
return Err(crate::error::builder(
|
return Err(crate::error::builder(
|
||||||
"Unknown TLS backend passed to `use_preconfigured_tls`"
|
"Unknown TLS backend passed to `use_preconfigured_tls`",
|
||||||
));
|
));
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "__tls"))]
|
#[cfg(not(feature = "__tls"))]
|
||||||
@@ -740,8 +731,8 @@ impl ClientBuilder {
|
|||||||
///
|
///
|
||||||
/// If `None`, the option will not be set.
|
/// If `None`, the option will not be set.
|
||||||
pub fn tcp_keepalive<D>(mut self, val: D) -> ClientBuilder
|
pub fn tcp_keepalive<D>(mut self, val: D) -> ClientBuilder
|
||||||
where
|
where
|
||||||
D: Into<Option<Duration>>,
|
D: Into<Option<Duration>>,
|
||||||
{
|
{
|
||||||
self.config.tcp_keepalive = val.into();
|
self.config.tcp_keepalive = val.into();
|
||||||
self
|
self
|
||||||
@@ -759,7 +750,14 @@ impl ClientBuilder {
|
|||||||
/// This requires the optional `default-tls`, `native-tls`, or `rustls-tls(-...)`
|
/// This requires the optional `default-tls`, `native-tls`, or `rustls-tls(-...)`
|
||||||
/// feature to be enabled.
|
/// feature to be enabled.
|
||||||
#[cfg(feature = "__tls")]
|
#[cfg(feature = "__tls")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(any(feature = "default-tls", feature = "native-tls", feature = "rustls-tls"))))]
|
#[cfg_attr(
|
||||||
|
docsrs,
|
||||||
|
doc(cfg(any(
|
||||||
|
feature = "default-tls",
|
||||||
|
feature = "native-tls",
|
||||||
|
feature = "rustls-tls"
|
||||||
|
)))
|
||||||
|
)]
|
||||||
pub fn add_root_certificate(mut self, cert: Certificate) -> ClientBuilder {
|
pub fn add_root_certificate(mut self, cert: Certificate) -> ClientBuilder {
|
||||||
self.config.root_certs.push(cert);
|
self.config.root_certs.push(cert);
|
||||||
self
|
self
|
||||||
@@ -774,11 +772,15 @@ impl ClientBuilder {
|
|||||||
/// This requires the optional `default-tls`, `native-tls`, or `rustls-tls(-...)`
|
/// This requires the optional `default-tls`, `native-tls`, or `rustls-tls(-...)`
|
||||||
/// feature to be enabled.
|
/// feature to be enabled.
|
||||||
#[cfg(feature = "__tls")]
|
#[cfg(feature = "__tls")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(any(feature = "default-tls", feature = "native-tls", feature = "rustls-tls"))))]
|
#[cfg_attr(
|
||||||
pub fn tls_built_in_root_certs(
|
docsrs,
|
||||||
mut self,
|
doc(cfg(any(
|
||||||
tls_built_in_root_certs: bool,
|
feature = "default-tls",
|
||||||
) -> ClientBuilder {
|
feature = "native-tls",
|
||||||
|
feature = "rustls-tls"
|
||||||
|
)))
|
||||||
|
)]
|
||||||
|
pub fn tls_built_in_root_certs(mut self, tls_built_in_root_certs: bool) -> ClientBuilder {
|
||||||
self.config.tls_built_in_root_certs = tls_built_in_root_certs;
|
self.config.tls_built_in_root_certs = tls_built_in_root_certs;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@@ -837,7 +839,14 @@ impl ClientBuilder {
|
|||||||
/// This requires the optional `default-tls`, `native-tls`, or `rustls-tls(-...)`
|
/// This requires the optional `default-tls`, `native-tls`, or `rustls-tls(-...)`
|
||||||
/// feature to be enabled.
|
/// feature to be enabled.
|
||||||
#[cfg(feature = "__tls")]
|
#[cfg(feature = "__tls")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(any(feature = "default-tls", feature = "native-tls", feature = "rustls-tls"))))]
|
#[cfg_attr(
|
||||||
|
docsrs,
|
||||||
|
doc(cfg(any(
|
||||||
|
feature = "default-tls",
|
||||||
|
feature = "native-tls",
|
||||||
|
feature = "rustls-tls"
|
||||||
|
)))
|
||||||
|
)]
|
||||||
pub fn danger_accept_invalid_certs(mut self, accept_invalid_certs: bool) -> ClientBuilder {
|
pub fn danger_accept_invalid_certs(mut self, accept_invalid_certs: bool) -> ClientBuilder {
|
||||||
self.config.certs_verification = !accept_invalid_certs;
|
self.config.certs_verification = !accept_invalid_certs;
|
||||||
self
|
self
|
||||||
@@ -891,16 +900,15 @@ impl ClientBuilder {
|
|||||||
///
|
///
|
||||||
/// This requires one of the optional features `native-tls` or
|
/// This requires one of the optional features `native-tls` or
|
||||||
/// `rustls-tls(-...)` to be enabled.
|
/// `rustls-tls(-...)` to be enabled.
|
||||||
#[cfg(any(
|
#[cfg(any(feature = "native-tls", feature = "__rustls",))]
|
||||||
feature = "native-tls",
|
|
||||||
feature = "__rustls",
|
|
||||||
))]
|
|
||||||
#[cfg_attr(docsrs, doc(cfg(any(feature = "native-tls", feature = "rustls-tls"))))]
|
#[cfg_attr(docsrs, doc(cfg(any(feature = "native-tls", feature = "rustls-tls"))))]
|
||||||
pub fn use_preconfigured_tls(mut self, tls: impl Any) -> ClientBuilder {
|
pub fn use_preconfigured_tls(mut self, tls: impl Any) -> ClientBuilder {
|
||||||
let mut tls = Some(tls);
|
let mut tls = Some(tls);
|
||||||
#[cfg(feature = "native-tls")]
|
#[cfg(feature = "native-tls")]
|
||||||
{
|
{
|
||||||
if let Some(conn) = (&mut tls as &mut dyn Any).downcast_mut::<Option<native_tls_crate::TlsConnector>>() {
|
if let Some(conn) =
|
||||||
|
(&mut tls as &mut dyn Any).downcast_mut::<Option<native_tls_crate::TlsConnector>>()
|
||||||
|
{
|
||||||
let tls = conn.take().expect("is definitely Some");
|
let tls = conn.take().expect("is definitely Some");
|
||||||
let tls = crate::tls::TlsBackend::BuiltNativeTls(tls);
|
let tls = crate::tls::TlsBackend::BuiltNativeTls(tls);
|
||||||
self.config.tls = tls;
|
self.config.tls = tls;
|
||||||
@@ -909,8 +917,9 @@ impl ClientBuilder {
|
|||||||
}
|
}
|
||||||
#[cfg(feature = "__rustls")]
|
#[cfg(feature = "__rustls")]
|
||||||
{
|
{
|
||||||
if let Some(conn) = (&mut tls as &mut dyn Any).downcast_mut::<Option<rustls::ClientConfig>>() {
|
if let Some(conn) =
|
||||||
|
(&mut tls as &mut dyn Any).downcast_mut::<Option<rustls::ClientConfig>>()
|
||||||
|
{
|
||||||
let tls = conn.take().expect("is definitely Some");
|
let tls = conn.take().expect("is definitely Some");
|
||||||
let tls = crate::tls::TlsBackend::BuiltRustls(tls);
|
let tls = crate::tls::TlsBackend::BuiltRustls(tls);
|
||||||
self.config.tls = tls;
|
self.config.tls = tls;
|
||||||
@@ -955,7 +964,7 @@ impl ClientBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Restrict the Client to be used with HTTPS only requests.
|
/// Restrict the Client to be used with HTTPS only requests.
|
||||||
///
|
///
|
||||||
/// Defaults to false.
|
/// Defaults to false.
|
||||||
pub fn https_only(mut self, enabled: bool) -> ClientBuilder {
|
pub fn https_only(mut self, enabled: bool) -> ClientBuilder {
|
||||||
self.config.https_only = enabled;
|
self.config.https_only = enabled;
|
||||||
@@ -1428,8 +1437,8 @@ impl Future for PendingRequest {
|
|||||||
.map(|cookie| cookie.into_inner().into_owned())
|
.map(|cookie| cookie.into_inner().into_owned())
|
||||||
.peekable();
|
.peekable();
|
||||||
if cookies.peek().is_some() {
|
if cookies.peek().is_some() {
|
||||||
let mut store = store_wrapper.write().unwrap();
|
let mut store = store_wrapper.write().unwrap();
|
||||||
store.0.store_response_cookies(cookies, &self.url);
|
store.0.store_response_cookies(cookies, &self.url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1600,7 +1609,8 @@ fn add_cookie_header(headers: &mut HeaderMap, cookie_store: &cookie::CookieStore
|
|||||||
|
|
||||||
#[cfg(feature = "rustls-tls-native-roots")]
|
#[cfg(feature = "rustls-tls-native-roots")]
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref NATIVE_ROOTS: std::io::Result<RootCertStore> = rustls_native_certs::load_native_certs().map_err(|e| e.1);
|
static ref NATIVE_ROOTS: std::io::Result<RootCertStore> =
|
||||||
|
rustls_native_certs::load_native_certs().map_err(|e| e.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -15,10 +15,10 @@ use futures_util::stream::Peekable;
|
|||||||
use http::HeaderMap;
|
use http::HeaderMap;
|
||||||
use hyper::body::HttpBody;
|
use hyper::body::HttpBody;
|
||||||
|
|
||||||
#[cfg(any(feature = "gzip", feature = "brotli"))]
|
|
||||||
use tokio_util::io::StreamReader;
|
|
||||||
#[cfg(any(feature = "gzip", feature = "brotli"))]
|
#[cfg(any(feature = "gzip", feature = "brotli"))]
|
||||||
use tokio_util::codec::{BytesCodec, FramedRead};
|
use tokio_util::codec::{BytesCodec, FramedRead};
|
||||||
|
#[cfg(any(feature = "gzip", feature = "brotli"))]
|
||||||
|
use tokio_util::io::StreamReader;
|
||||||
|
|
||||||
use super::super::Body;
|
use super::super::Body;
|
||||||
use crate::error;
|
use crate::error;
|
||||||
@@ -190,11 +190,7 @@ impl Decoder {
|
|||||||
/// how to decode the content body of the request.
|
/// how to decode the content body of the request.
|
||||||
///
|
///
|
||||||
/// Uses the correct variant by inspecting the Content-Encoding header.
|
/// Uses the correct variant by inspecting the Content-Encoding header.
|
||||||
pub(super) fn detect(
|
pub(super) fn detect(_headers: &mut HeaderMap, body: Body, _accepts: Accepts) -> Decoder {
|
||||||
_headers: &mut HeaderMap,
|
|
||||||
body: Body,
|
|
||||||
_accepts: Accepts,
|
|
||||||
) -> Decoder {
|
|
||||||
#[cfg(feature = "gzip")]
|
#[cfg(feature = "gzip")]
|
||||||
{
|
{
|
||||||
if _accepts.gzip && Decoder::detect_gzip(_headers) {
|
if _accepts.gzip && Decoder::detect_gzip(_headers) {
|
||||||
@@ -307,9 +303,15 @@ impl Future for Pending {
|
|||||||
|
|
||||||
match self.1 {
|
match self.1 {
|
||||||
#[cfg(feature = "brotli")]
|
#[cfg(feature = "brotli")]
|
||||||
DecoderType::Brotli => Poll::Ready(Ok(Inner::Brotli(FramedRead::new(BrotliDecoder::new(StreamReader::new(_body)), BytesCodec::new())))),
|
DecoderType::Brotli => Poll::Ready(Ok(Inner::Brotli(FramedRead::new(
|
||||||
|
BrotliDecoder::new(StreamReader::new(_body)),
|
||||||
|
BytesCodec::new(),
|
||||||
|
)))),
|
||||||
#[cfg(feature = "gzip")]
|
#[cfg(feature = "gzip")]
|
||||||
DecoderType::Gzip => Poll::Ready(Ok(Inner::Gzip(FramedRead::new(GzipDecoder::new(StreamReader::new(_body)), BytesCodec::new())))),
|
DecoderType::Gzip => Poll::Ready(Ok(Inner::Gzip(FramedRead::new(
|
||||||
|
GzipDecoder::new(StreamReader::new(_body)),
|
||||||
|
BytesCodec::new(),
|
||||||
|
)))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -521,7 +521,10 @@ mod tests {
|
|||||||
fn form_empty() {
|
fn form_empty() {
|
||||||
let form = Form::new();
|
let form = Form::new();
|
||||||
|
|
||||||
let rt = runtime::Builder::new_current_thread().enable_all().build().expect("new rt");
|
let rt = runtime::Builder::new_current_thread()
|
||||||
|
.enable_all()
|
||||||
|
.build()
|
||||||
|
.expect("new rt");
|
||||||
let body = form.stream().into_stream();
|
let body = form.stream().into_stream();
|
||||||
let s = body.map_ok(|try_c| try_c.to_vec()).try_concat();
|
let s = body.map_ok(|try_c| try_c.to_vec()).try_concat();
|
||||||
|
|
||||||
@@ -568,7 +571,10 @@ mod tests {
|
|||||||
--boundary\r\n\
|
--boundary\r\n\
|
||||||
Content-Disposition: form-data; name=\"key3\"; filename=\"filename\"\r\n\r\n\
|
Content-Disposition: form-data; name=\"key3\"; filename=\"filename\"\r\n\r\n\
|
||||||
value3\r\n--boundary--\r\n";
|
value3\r\n--boundary--\r\n";
|
||||||
let rt = runtime::Builder::new_current_thread().enable_all().build().expect("new rt");
|
let rt = runtime::Builder::new_current_thread()
|
||||||
|
.enable_all()
|
||||||
|
.build()
|
||||||
|
.expect("new rt");
|
||||||
let body = form.stream().into_stream();
|
let body = form.stream().into_stream();
|
||||||
let s = body.map(|try_c| try_c.map(|r| r.to_vec())).try_concat();
|
let s = body.map(|try_c| try_c.map(|r| r.to_vec())).try_concat();
|
||||||
|
|
||||||
@@ -595,7 +601,10 @@ mod tests {
|
|||||||
\r\n\
|
\r\n\
|
||||||
value2\r\n\
|
value2\r\n\
|
||||||
--boundary--\r\n";
|
--boundary--\r\n";
|
||||||
let rt = runtime::Builder::new_current_thread().enable_all().build().expect("new rt");
|
let rt = runtime::Builder::new_current_thread()
|
||||||
|
.enable_all()
|
||||||
|
.build()
|
||||||
|
.expect("new rt");
|
||||||
let body = form.stream().into_stream();
|
let body = form.stream().into_stream();
|
||||||
let s = body.map(|try_c| try_c.map(|r| r.to_vec())).try_concat();
|
let s = body.map(|try_c| try_c.map(|r| r.to_vec())).try_concat();
|
||||||
|
|
||||||
|
|||||||
@@ -14,11 +14,11 @@ use super::client::{Client, Pending};
|
|||||||
#[cfg(feature = "multipart")]
|
#[cfg(feature = "multipart")]
|
||||||
use super::multipart;
|
use super::multipart;
|
||||||
use super::response::Response;
|
use super::response::Response;
|
||||||
use crate::header::{HeaderMap, HeaderName, HeaderValue, CONTENT_TYPE};
|
|
||||||
#[cfg(feature = "multipart")]
|
#[cfg(feature = "multipart")]
|
||||||
use crate::header::CONTENT_LENGTH;
|
use crate::header::CONTENT_LENGTH;
|
||||||
|
use crate::header::{HeaderMap, HeaderName, HeaderValue, CONTENT_TYPE};
|
||||||
use crate::{Method, Url};
|
use crate::{Method, Url};
|
||||||
use http::{Request as HttpRequest, request::Parts};
|
use http::{request::Parts, Request as HttpRequest};
|
||||||
|
|
||||||
/// A request which can be executed with `Client::execute()`.
|
/// A request which can be executed with `Client::execute()`.
|
||||||
pub struct Request {
|
pub struct Request {
|
||||||
@@ -47,7 +47,7 @@ impl Request {
|
|||||||
url,
|
url,
|
||||||
headers: HeaderMap::new(),
|
headers: HeaderMap::new(),
|
||||||
body: None,
|
body: None,
|
||||||
timeout: None
|
timeout: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,7 +154,7 @@ impl RequestBuilder {
|
|||||||
HeaderName: TryFrom<K>,
|
HeaderName: TryFrom<K>,
|
||||||
<HeaderName as TryFrom<K>>::Error: Into<http::Error>,
|
<HeaderName as TryFrom<K>>::Error: Into<http::Error>,
|
||||||
HeaderValue: TryFrom<V>,
|
HeaderValue: TryFrom<V>,
|
||||||
<HeaderValue as TryFrom<V>>::Error: Into<http::Error>,
|
<HeaderValue as TryFrom<V>>::Error: Into<http::Error>,
|
||||||
{
|
{
|
||||||
self.header_sensitive(key, value, false)
|
self.header_sensitive(key, value, false)
|
||||||
}
|
}
|
||||||
@@ -476,7 +476,6 @@ fn fmt_request_fields<'a, 'b>(
|
|||||||
.field("headers", &req.headers)
|
.field("headers", &req.headers)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Check the request URL for a "username:password" type authority, and if
|
/// Check the request URL for a "username:password" type authority, and if
|
||||||
/// found, remove it from the URL and return it.
|
/// found, remove it from the URL and return it.
|
||||||
pub(crate) fn extract_authority(url: &mut Url) -> Option<(String, Option<String>)> {
|
pub(crate) fn extract_authority(url: &mut Url) -> Option<(String, Option<String>)> {
|
||||||
@@ -494,20 +493,21 @@ pub(crate) fn extract_authority(url: &mut Url) -> Option<(String, Option<String>
|
|||||||
.map(String::from)
|
.map(String::from)
|
||||||
});
|
});
|
||||||
if !username.is_empty() || password.is_some() {
|
if !username.is_empty() || password.is_some() {
|
||||||
url
|
url.set_username("")
|
||||||
.set_username("")
|
|
||||||
.expect("has_authority means set_username shouldn't fail");
|
.expect("has_authority means set_username shouldn't fail");
|
||||||
url
|
url.set_password(None)
|
||||||
.set_password(None)
|
|
||||||
.expect("has_authority means set_password shouldn't fail");
|
.expect("has_authority means set_password shouldn't fail");
|
||||||
return Some((username, password))
|
return Some((username, password));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> TryFrom<HttpRequest<T>> for Request where T:Into<Body>{
|
impl<T> TryFrom<HttpRequest<T>> for Request
|
||||||
|
where
|
||||||
|
T: Into<Body>,
|
||||||
|
{
|
||||||
type Error = crate::Error;
|
type Error = crate::Error;
|
||||||
|
|
||||||
fn try_from(req: HttpRequest<T>) -> crate::Result<Self> {
|
fn try_from(req: HttpRequest<T>) -> crate::Result<Self> {
|
||||||
@@ -518,8 +518,7 @@ impl<T> TryFrom<HttpRequest<T>> for Request where T:Into<Body>{
|
|||||||
headers,
|
headers,
|
||||||
..
|
..
|
||||||
} = parts;
|
} = parts;
|
||||||
let url = Url::parse(&uri.to_string())
|
let url = Url::parse(&uri.to_string()).map_err(crate::error::builder)?;
|
||||||
.map_err(crate::error::builder)?;
|
|
||||||
Ok(Request {
|
Ok(Request {
|
||||||
method,
|
method,
|
||||||
url,
|
url,
|
||||||
@@ -646,7 +645,8 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn try_clone_reusable() {
|
fn try_clone_reusable() {
|
||||||
let client = Client::new();
|
let client = Client::new();
|
||||||
let builder = client.post("http://httpbin.org/post")
|
let builder = client
|
||||||
|
.post("http://httpbin.org/post")
|
||||||
.header("foo", "bar")
|
.header("foo", "bar")
|
||||||
.body("from a &str!");
|
.body("from a &str!");
|
||||||
let req = builder
|
let req = builder
|
||||||
@@ -676,14 +676,11 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
#[cfg(feature = "stream")]
|
#[cfg(feature = "stream")]
|
||||||
fn try_clone_stream() {
|
fn try_clone_stream() {
|
||||||
let chunks: Vec<Result<_, ::std::io::Error>> = vec![
|
let chunks: Vec<Result<_, ::std::io::Error>> = vec![Ok("hello"), Ok(" "), Ok("world")];
|
||||||
Ok("hello"),
|
|
||||||
Ok(" "),
|
|
||||||
Ok("world"),
|
|
||||||
];
|
|
||||||
let stream = futures_util::stream::iter(chunks);
|
let stream = futures_util::stream::iter(chunks);
|
||||||
let client = Client::new();
|
let client = Client::new();
|
||||||
let builder = client.get("http://httpbin.org/get")
|
let builder = client
|
||||||
|
.get("http://httpbin.org/get")
|
||||||
.body(super::Body::wrap_stream(stream));
|
.body(super::Body::wrap_stream(stream));
|
||||||
let clone = builder.try_clone();
|
let clone = builder.try_clone();
|
||||||
assert!(clone.is_none());
|
assert!(clone.is_none());
|
||||||
@@ -694,13 +691,13 @@ mod tests {
|
|||||||
let client = Client::new();
|
let client = Client::new();
|
||||||
let some_url = "https://Aladdin:open sesame@localhost/";
|
let some_url = "https://Aladdin:open sesame@localhost/";
|
||||||
|
|
||||||
let req = client
|
let req = client.get(some_url).build().expect("request build");
|
||||||
.get(some_url)
|
|
||||||
.build()
|
|
||||||
.expect("request build");
|
|
||||||
|
|
||||||
assert_eq!(req.url().as_str(), "https://localhost/");
|
assert_eq!(req.url().as_str(), "https://localhost/");
|
||||||
assert_eq!(req.headers()["authorization"], "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==");
|
assert_eq!(
|
||||||
|
req.headers()["authorization"],
|
||||||
|
"Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -715,7 +712,10 @@ mod tests {
|
|||||||
.expect("request build");
|
.expect("request build");
|
||||||
|
|
||||||
assert_eq!(req.url().as_str(), "https://localhost/");
|
assert_eq!(req.url().as_str(), "https://localhost/");
|
||||||
assert_eq!(req.headers()["authorization"], "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==");
|
assert_eq!(
|
||||||
|
req.headers()["authorization"],
|
||||||
|
"Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="
|
||||||
|
);
|
||||||
assert_eq!(req.headers()["authorization"].is_sensitive(), true);
|
assert_eq!(req.headers()["authorization"].is_sensitive(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -735,11 +735,10 @@ mod tests {
|
|||||||
assert_eq!(req.headers()["authorization"].is_sensitive(), true);
|
assert_eq!(req.headers()["authorization"].is_sensitive(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn convert_from_http_request() {
|
fn convert_from_http_request() {
|
||||||
let http_request = HttpRequest::builder().method("GET")
|
let http_request = HttpRequest::builder()
|
||||||
|
.method("GET")
|
||||||
.uri("http://localhost/")
|
.uri("http://localhost/")
|
||||||
.header("User-Agent", "my-awesome-agent/1.0")
|
.header("User-Agent", "my-awesome-agent/1.0")
|
||||||
.body("test test test")
|
.body("test test test")
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
use std::io::{self, Read};
|
|
||||||
#[cfg(feature = "multipart")]
|
#[cfg(feature = "multipart")]
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
|
use std::io::{self, Read};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
|
||||||
use bytes::Bytes;
|
|
||||||
use bytes::buf::UninitSlice;
|
use bytes::buf::UninitSlice;
|
||||||
|
use bytes::Bytes;
|
||||||
|
|
||||||
use crate::async_impl;
|
use crate::async_impl;
|
||||||
|
|
||||||
@@ -95,7 +95,7 @@ impl Body {
|
|||||||
/// Converts streamed requests to their buffered equivalent and
|
/// Converts streamed requests to their buffered equivalent and
|
||||||
/// returns a reference to the buffer. If the request is already
|
/// returns a reference to the buffer. If the request is already
|
||||||
/// buffered, this has no effect.
|
/// buffered, this has no effect.
|
||||||
///
|
///
|
||||||
/// Be aware that for large requests this method is expensive
|
/// Be aware that for large requests this method is expensive
|
||||||
/// and may cause your program to run out of memory.
|
/// and may cause your program to run out of memory.
|
||||||
pub fn buffer(&mut self) -> Result<&[u8], crate::Error> {
|
pub fn buffer(&mut self) -> Result<&[u8], crate::Error> {
|
||||||
@@ -106,11 +106,10 @@ impl Body {
|
|||||||
} else {
|
} else {
|
||||||
Vec::new()
|
Vec::new()
|
||||||
};
|
};
|
||||||
io::copy(reader, &mut bytes)
|
io::copy(reader, &mut bytes).map_err(crate::error::builder)?;
|
||||||
.map_err(crate::error::builder)?;
|
|
||||||
self.kind = Kind::Bytes(bytes.into());
|
self.kind = Kind::Bytes(bytes.into());
|
||||||
self.buffer()
|
self.buffer()
|
||||||
},
|
}
|
||||||
Kind::Bytes(ref bytes) => Ok(bytes.as_ref()),
|
Kind::Bytes(ref bytes) => Ok(bytes.as_ref()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -302,9 +301,7 @@ async fn send_future(sender: Sender) -> Result<(), crate::Error> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let bytes = unsafe {
|
let bytes = unsafe { mem::transmute::<&mut UninitSlice, &mut [u8]>(buf.chunk_mut()) };
|
||||||
mem::transmute::<&mut UninitSlice, &mut [u8]>(buf.chunk_mut())
|
|
||||||
};
|
|
||||||
match body.read(bytes) {
|
match body.read(bytes) {
|
||||||
Ok(0) => {
|
Ok(0) => {
|
||||||
// The buffer was empty and nothing's left to
|
// The buffer was empty and nothing's left to
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
#[cfg(any(
|
#[cfg(any(feature = "native-tls", feature = "__rustls",))]
|
||||||
feature = "native-tls",
|
|
||||||
feature = "__rustls",
|
|
||||||
))]
|
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
@@ -18,11 +15,11 @@ use tokio::sync::{mpsc, oneshot};
|
|||||||
use super::request::{Request, RequestBuilder};
|
use super::request::{Request, RequestBuilder};
|
||||||
use super::response::Response;
|
use super::response::Response;
|
||||||
use super::wait;
|
use super::wait;
|
||||||
use crate::{async_impl, header, IntoUrl, Method, Proxy, redirect};
|
|
||||||
#[cfg(feature = "__tls")]
|
#[cfg(feature = "__tls")]
|
||||||
use crate::Certificate;
|
use crate::Certificate;
|
||||||
#[cfg(any(feature = "native-tls", feature = "__rustls"))]
|
#[cfg(any(feature = "native-tls", feature = "__rustls"))]
|
||||||
use crate::Identity;
|
use crate::Identity;
|
||||||
|
use crate::{async_impl, header, redirect, IntoUrl, Method, Proxy};
|
||||||
|
|
||||||
/// A `Client` to make Requests with.
|
/// A `Client` to make Requests with.
|
||||||
///
|
///
|
||||||
@@ -103,10 +100,8 @@ impl ClientBuilder {
|
|||||||
ClientHandle::new(self).map(|handle| Client { inner: handle })
|
ClientHandle::new(self).map(|handle| Client { inner: handle })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Higher-level options
|
// Higher-level options
|
||||||
|
|
||||||
|
|
||||||
/// Sets the `User-Agent` header to be used by this client.
|
/// Sets the `User-Agent` header to be used by this client.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
@@ -239,7 +234,9 @@ impl ClientBuilder {
|
|||||||
/// This requires the optional `brotli` feature to be enabled
|
/// This requires the optional `brotli` feature to be enabled
|
||||||
#[cfg(feature = "brotli")]
|
#[cfg(feature = "brotli")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "brotli")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "brotli")))]
|
||||||
pub fn brotli(self, enable: bool) -> ClientBuilder { self.with_inner(|inner| inner.brotli(enable)) }
|
pub fn brotli(self, enable: bool) -> ClientBuilder {
|
||||||
|
self.with_inner(|inner| inner.brotli(enable))
|
||||||
|
}
|
||||||
|
|
||||||
/// Disable auto response body gzip decompression.
|
/// Disable auto response body gzip decompression.
|
||||||
///
|
///
|
||||||
@@ -255,7 +252,9 @@ impl ClientBuilder {
|
|||||||
/// This method exists even if the optional `brotli` feature is not enabled.
|
/// This method exists even if the optional `brotli` feature is not enabled.
|
||||||
/// This can be used to ensure a `Client` doesn't use brotli decompression
|
/// This can be used to ensure a `Client` doesn't use brotli decompression
|
||||||
/// even if another dependency were to enable the optional `brotli` feature.
|
/// even if another dependency were to enable the optional `brotli` feature.
|
||||||
pub fn no_brotli(self) -> ClientBuilder { self.with_inner(|inner| inner.no_brotli()) }
|
pub fn no_brotli(self) -> ClientBuilder {
|
||||||
|
self.with_inner(|inner| inner.no_brotli())
|
||||||
|
}
|
||||||
|
|
||||||
// Redirect options
|
// Redirect options
|
||||||
|
|
||||||
@@ -420,8 +419,8 @@ impl ClientBuilder {
|
|||||||
///
|
///
|
||||||
/// If `None`, the option will not be set.
|
/// If `None`, the option will not be set.
|
||||||
pub fn tcp_keepalive<D>(self, val: D) -> ClientBuilder
|
pub fn tcp_keepalive<D>(self, val: D) -> ClientBuilder
|
||||||
where
|
where
|
||||||
D: Into<Option<Duration>>,
|
D: Into<Option<Duration>>,
|
||||||
{
|
{
|
||||||
self.with_inner(move |inner| inner.tcp_keepalive(val))
|
self.with_inner(move |inner| inner.tcp_keepalive(val))
|
||||||
}
|
}
|
||||||
@@ -460,7 +459,14 @@ impl ClientBuilder {
|
|||||||
/// This requires the optional `default-tls`, `native-tls`, or `rustls-tls(-...)`
|
/// This requires the optional `default-tls`, `native-tls`, or `rustls-tls(-...)`
|
||||||
/// feature to be enabled.
|
/// feature to be enabled.
|
||||||
#[cfg(feature = "__tls")]
|
#[cfg(feature = "__tls")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(any(feature = "default-tls", feature = "native-tls", feature = "rustls-tls"))))]
|
#[cfg_attr(
|
||||||
|
docsrs,
|
||||||
|
doc(cfg(any(
|
||||||
|
feature = "default-tls",
|
||||||
|
feature = "native-tls",
|
||||||
|
feature = "rustls-tls"
|
||||||
|
)))
|
||||||
|
)]
|
||||||
pub fn add_root_certificate(self, cert: Certificate) -> ClientBuilder {
|
pub fn add_root_certificate(self, cert: Certificate) -> ClientBuilder {
|
||||||
self.with_inner(move |inner| inner.add_root_certificate(cert))
|
self.with_inner(move |inner| inner.add_root_certificate(cert))
|
||||||
}
|
}
|
||||||
@@ -474,11 +480,15 @@ impl ClientBuilder {
|
|||||||
/// This requires the optional `default-tls`, `native-tls`, or `rustls-tls(-...)`
|
/// This requires the optional `default-tls`, `native-tls`, or `rustls-tls(-...)`
|
||||||
/// feature to be enabled.
|
/// feature to be enabled.
|
||||||
#[cfg(feature = "__tls")]
|
#[cfg(feature = "__tls")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(any(feature = "default-tls", feature = "native-tls", feature = "rustls-tls"))))]
|
#[cfg_attr(
|
||||||
pub fn tls_built_in_root_certs(
|
docsrs,
|
||||||
self,
|
doc(cfg(any(
|
||||||
tls_built_in_root_certs: bool,
|
feature = "default-tls",
|
||||||
) -> ClientBuilder {
|
feature = "native-tls",
|
||||||
|
feature = "rustls-tls"
|
||||||
|
)))
|
||||||
|
)]
|
||||||
|
pub fn tls_built_in_root_certs(self, tls_built_in_root_certs: bool) -> ClientBuilder {
|
||||||
self.with_inner(move |inner| inner.tls_built_in_root_certs(tls_built_in_root_certs))
|
self.with_inner(move |inner| inner.tls_built_in_root_certs(tls_built_in_root_certs))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -526,7 +536,14 @@ impl ClientBuilder {
|
|||||||
/// introduces significant vulnerabilities, and should only be used
|
/// introduces significant vulnerabilities, and should only be used
|
||||||
/// as a last resort.
|
/// as a last resort.
|
||||||
#[cfg(feature = "__tls")]
|
#[cfg(feature = "__tls")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(any(feature = "default-tls", feature = "native-tls", feature = "rustls-tls"))))]
|
#[cfg_attr(
|
||||||
|
docsrs,
|
||||||
|
doc(cfg(any(
|
||||||
|
feature = "default-tls",
|
||||||
|
feature = "native-tls",
|
||||||
|
feature = "rustls-tls"
|
||||||
|
)))
|
||||||
|
)]
|
||||||
pub fn danger_accept_invalid_certs(self, accept_invalid_certs: bool) -> ClientBuilder {
|
pub fn danger_accept_invalid_certs(self, accept_invalid_certs: bool) -> ClientBuilder {
|
||||||
self.with_inner(|inner| inner.danger_accept_invalid_certs(accept_invalid_certs))
|
self.with_inner(|inner| inner.danger_accept_invalid_certs(accept_invalid_certs))
|
||||||
}
|
}
|
||||||
@@ -577,10 +594,7 @@ impl ClientBuilder {
|
|||||||
///
|
///
|
||||||
/// This requires one of the optional features `native-tls` or
|
/// This requires one of the optional features `native-tls` or
|
||||||
/// `rustls-tls(-...)` to be enabled.
|
/// `rustls-tls(-...)` to be enabled.
|
||||||
#[cfg(any(
|
#[cfg(any(feature = "native-tls", feature = "__rustls",))]
|
||||||
feature = "native-tls",
|
|
||||||
feature = "__rustls",
|
|
||||||
))]
|
|
||||||
#[cfg_attr(docsrs, doc(cfg(any(feature = "native-tls", feature = "rustls-tls"))))]
|
#[cfg_attr(docsrs, doc(cfg(any(feature = "native-tls", feature = "rustls-tls"))))]
|
||||||
pub fn use_preconfigured_tls(self, tls: impl Any) -> ClientBuilder {
|
pub fn use_preconfigured_tls(self, tls: impl Any) -> ClientBuilder {
|
||||||
self.with_inner(move |inner| inner.use_preconfigured_tls(tls))
|
self.with_inner(move |inner| inner.use_preconfigured_tls(tls))
|
||||||
@@ -609,7 +623,7 @@ impl ClientBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Restrict the Client to be used with HTTPS only requests.
|
/// Restrict the Client to be used with HTTPS only requests.
|
||||||
///
|
///
|
||||||
/// Defaults to false.
|
/// Defaults to false.
|
||||||
pub fn https_only(self, enabled: bool) -> ClientBuilder {
|
pub fn https_only(self, enabled: bool) -> ClientBuilder {
|
||||||
self.with_inner(|inner| inner.https_only(enabled))
|
self.with_inner(|inner| inner.https_only(enabled))
|
||||||
@@ -781,7 +795,8 @@ struct InnerClientHandle {
|
|||||||
|
|
||||||
impl Drop for InnerClientHandle {
|
impl Drop for InnerClientHandle {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
let id = self.thread
|
let id = self
|
||||||
|
.thread
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|h| h.thread().id())
|
.map(|h| h.thread().id())
|
||||||
.expect("thread not dropped yet");
|
.expect("thread not dropped yet");
|
||||||
@@ -804,7 +819,11 @@ impl ClientHandle {
|
|||||||
.name("reqwest-internal-sync-runtime".into())
|
.name("reqwest-internal-sync-runtime".into())
|
||||||
.spawn(move || {
|
.spawn(move || {
|
||||||
use tokio::runtime;
|
use tokio::runtime;
|
||||||
let rt = match runtime::Builder::new_current_thread().enable_all().build().map_err(crate::error::builder) {
|
let rt = match runtime::Builder::new_current_thread()
|
||||||
|
.enable_all()
|
||||||
|
.build()
|
||||||
|
.map_err(crate::error::builder)
|
||||||
|
{
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
if let Err(e) = spawn_tx.send(Err(e)) {
|
if let Err(e) = spawn_tx.send(Err(e)) {
|
||||||
error!("Failed to communicate runtime creation failure: {:?}", e);
|
error!("Failed to communicate runtime creation failure: {:?}", e);
|
||||||
@@ -886,9 +905,7 @@ impl ClientHandle {
|
|||||||
};
|
};
|
||||||
wait::timeout(f, timeout)
|
wait::timeout(f, timeout)
|
||||||
} else {
|
} else {
|
||||||
let f = async move {
|
let f = async move { rx.await.map_err(|_canceled| event_loop_panicked()) };
|
||||||
rx.await.map_err(|_canceled| event_loop_panicked())
|
|
||||||
};
|
|
||||||
wait::timeout(f, timeout)
|
wait::timeout(f, timeout)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -392,8 +392,7 @@ mod tests {
|
|||||||
.part("key3", Part::text("value3").file_name("filename"));
|
.part("key3", Part::text("value3").file_name("filename"));
|
||||||
form.inner.boundary = "boundary".to_string();
|
form.inner.boundary = "boundary".to_string();
|
||||||
let length = form.compute_length();
|
let length = form.compute_length();
|
||||||
let expected =
|
let expected = "--boundary\r\n\
|
||||||
"--boundary\r\n\
|
|
||||||
Content-Disposition: form-data; name=\"reader1\"\r\n\r\n\
|
Content-Disposition: form-data; name=\"reader1\"\r\n\r\n\
|
||||||
\r\n\
|
\r\n\
|
||||||
--boundary\r\n\
|
--boundary\r\n\
|
||||||
@@ -429,8 +428,7 @@ mod tests {
|
|||||||
.part("key3", Part::text("value3").file_name("filename"));
|
.part("key3", Part::text("value3").file_name("filename"));
|
||||||
form.inner.boundary = "boundary".to_string();
|
form.inner.boundary = "boundary".to_string();
|
||||||
let length = form.compute_length();
|
let length = form.compute_length();
|
||||||
let expected =
|
let expected = "--boundary\r\n\
|
||||||
"--boundary\r\n\
|
|
||||||
Content-Disposition: form-data; name=\"key1\"\r\n\r\n\
|
Content-Disposition: form-data; name=\"key1\"\r\n\r\n\
|
||||||
value1\r\n\
|
value1\r\n\
|
||||||
--boundary\r\n\
|
--boundary\r\n\
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
use std::fmt;
|
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
use std::fmt;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use base64::encode;
|
use base64::encode;
|
||||||
use http::{Request as HttpRequest, request::Parts};
|
use http::{request::Parts, Request as HttpRequest};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
#[cfg(feature = "json")]
|
#[cfg(feature = "json")]
|
||||||
use serde_json;
|
use serde_json;
|
||||||
@@ -598,7 +598,10 @@ impl RequestBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> TryFrom<HttpRequest<T>> for Request where T:Into<Body> {
|
impl<T> TryFrom<HttpRequest<T>> for Request
|
||||||
|
where
|
||||||
|
T: Into<Body>,
|
||||||
|
{
|
||||||
type Error = crate::Error;
|
type Error = crate::Error;
|
||||||
|
|
||||||
fn try_from(req: HttpRequest<T>) -> crate::Result<Self> {
|
fn try_from(req: HttpRequest<T>) -> crate::Result<Self> {
|
||||||
@@ -609,8 +612,7 @@ impl<T> TryFrom<HttpRequest<T>> for Request where T:Into<Body> {
|
|||||||
headers,
|
headers,
|
||||||
..
|
..
|
||||||
} = parts;
|
} = parts;
|
||||||
let url = Url::parse(&uri.to_string())
|
let url = Url::parse(&uri.to_string()).map_err(crate::error::builder)?;
|
||||||
.map_err(crate::error::builder)?;
|
|
||||||
let mut inner = async_impl::Request::new(method, url);
|
let mut inner = async_impl::Request::new(method, url);
|
||||||
crate::util::replace_headers(inner.headers_mut(), headers);
|
crate::util::replace_headers(inner.headers_mut(), headers);
|
||||||
Ok(Request {
|
Ok(Request {
|
||||||
@@ -637,8 +639,8 @@ fn fmt_request_fields<'a, 'b>(
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::{HttpRequest, Request};
|
|
||||||
use super::super::{body, Client};
|
use super::super::{body, Client};
|
||||||
|
use super::{HttpRequest, Request};
|
||||||
use crate::header::{HeaderMap, HeaderValue, ACCEPT, CONTENT_TYPE, HOST};
|
use crate::header::{HeaderMap, HeaderValue, ACCEPT, CONTENT_TYPE, HOST};
|
||||||
use crate::Method;
|
use crate::Method;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
@@ -959,18 +961,19 @@ mod tests {
|
|||||||
let client = Client::new();
|
let client = Client::new();
|
||||||
let some_url = "https://Aladdin:open sesame@localhost/";
|
let some_url = "https://Aladdin:open sesame@localhost/";
|
||||||
|
|
||||||
let req = client
|
let req = client.get(some_url).build().expect("request build");
|
||||||
.get(some_url)
|
|
||||||
.build()
|
|
||||||
.expect("request build");
|
|
||||||
|
|
||||||
assert_eq!(req.url().as_str(), "https://localhost/");
|
assert_eq!(req.url().as_str(), "https://localhost/");
|
||||||
assert_eq!(req.headers()["authorization"], "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==");
|
assert_eq!(
|
||||||
|
req.headers()["authorization"],
|
||||||
|
"Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn convert_from_http_request() {
|
fn convert_from_http_request() {
|
||||||
let http_request = HttpRequest::builder().method("GET")
|
let http_request = HttpRequest::builder()
|
||||||
|
.method("GET")
|
||||||
.uri("http://localhost/")
|
.uri("http://localhost/")
|
||||||
.header("User-Agent", "my-awesome-agent/1.0")
|
.header("User-Agent", "my-awesome-agent/1.0")
|
||||||
.body("test test test")
|
.body("test test test")
|
||||||
@@ -997,7 +1000,10 @@ mod tests {
|
|||||||
.expect("request build");
|
.expect("request build");
|
||||||
|
|
||||||
assert_eq!(req.url().as_str(), "https://localhost/");
|
assert_eq!(req.url().as_str(), "https://localhost/");
|
||||||
assert_eq!(req.headers()["authorization"], "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==");
|
assert_eq!(
|
||||||
|
req.headers()["authorization"],
|
||||||
|
"Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="
|
||||||
|
);
|
||||||
assert_eq!(req.headers()["authorization"].is_sensitive(), true);
|
assert_eq!(req.headers()["authorization"].is_sensitive(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ use std::time::Duration;
|
|||||||
|
|
||||||
use tokio::time::Instant;
|
use tokio::time::Instant;
|
||||||
|
|
||||||
|
|
||||||
pub(crate) fn timeout<F, I, E>(fut: F, timeout: Option<Duration>) -> Result<I, Waited<E>>
|
pub(crate) fn timeout<F, I, E>(fut: F, timeout: Option<Duration>) -> Result<I, Waited<E>>
|
||||||
where
|
where
|
||||||
F: Future<Output = Result<I, E>>,
|
F: Future<Output = Result<I, E>>,
|
||||||
@@ -40,7 +39,11 @@ where
|
|||||||
return Err(Waited::TimedOut(crate::error::TimedOut));
|
return Err(Waited::TimedOut(crate::error::TimedOut));
|
||||||
}
|
}
|
||||||
|
|
||||||
log::trace!("({:?}) park timeout {:?}", thread::current().id(), deadline - now);
|
log::trace!(
|
||||||
|
"({:?}) park timeout {:?}",
|
||||||
|
thread::current().id(),
|
||||||
|
deadline - now
|
||||||
|
);
|
||||||
thread::park_timeout(deadline - now);
|
thread::park_timeout(deadline - now);
|
||||||
} else {
|
} else {
|
||||||
log::trace!("({:?}) park without timeout", thread::current().id());
|
log::trace!("({:?}) park without timeout", thread::current().id());
|
||||||
|
|||||||
211
src/connect.rs
211
src/connect.rs
@@ -1,14 +1,15 @@
|
|||||||
use hyper::service::Service;
|
use futures_util::future::Either;
|
||||||
use http::uri::{Scheme, Authority};
|
|
||||||
use http::Uri;
|
|
||||||
use hyper::client::connect::{Connected, Connection};
|
|
||||||
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
|
|
||||||
#[cfg(feature = "native-tls-crate")]
|
|
||||||
use native_tls_crate::{TlsConnector, TlsConnectorBuilder};
|
|
||||||
#[cfg(feature = "__tls")]
|
#[cfg(feature = "__tls")]
|
||||||
use http::header::HeaderValue;
|
use http::header::HeaderValue;
|
||||||
use futures_util::future::Either;
|
use http::uri::{Authority, Scheme};
|
||||||
|
use http::Uri;
|
||||||
|
use hyper::client::connect::{Connected, Connection};
|
||||||
|
use hyper::service::Service;
|
||||||
|
#[cfg(feature = "native-tls-crate")]
|
||||||
|
use native_tls_crate::{TlsConnector, TlsConnectorBuilder};
|
||||||
|
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
|
||||||
|
|
||||||
|
use pin_project_lite::pin_project;
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::io::IoSlice;
|
use std::io::IoSlice;
|
||||||
@@ -17,16 +18,15 @@ use std::pin::Pin;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::task::{Context, Poll};
|
use std::task::{Context, Poll};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use pin_project_lite::pin_project;
|
|
||||||
|
|
||||||
#[cfg(feature = "trust-dns")]
|
|
||||||
use crate::dns::TrustDnsResolver;
|
|
||||||
use crate::proxy::{Proxy, ProxyScheme};
|
|
||||||
use crate::error::BoxError;
|
|
||||||
#[cfg(feature = "default-tls")]
|
#[cfg(feature = "default-tls")]
|
||||||
use self::native_tls_conn::NativeTlsConn;
|
use self::native_tls_conn::NativeTlsConn;
|
||||||
#[cfg(feature = "__rustls")]
|
#[cfg(feature = "__rustls")]
|
||||||
use self::rustls_tls_conn::RustlsTlsConn;
|
use self::rustls_tls_conn::RustlsTlsConn;
|
||||||
|
#[cfg(feature = "trust-dns")]
|
||||||
|
use crate::dns::TrustDnsResolver;
|
||||||
|
use crate::error::BoxError;
|
||||||
|
use crate::proxy::{Proxy, ProxyScheme};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub(crate) enum HttpConnector {
|
pub(crate) enum HttpConnector {
|
||||||
@@ -165,25 +165,21 @@ impl Connector {
|
|||||||
{
|
{
|
||||||
let tls = tls.build().map_err(crate::error::builder)?;
|
let tls = tls.build().map_err(crate::error::builder)?;
|
||||||
Ok(Self::from_built_default_tls(
|
Ok(Self::from_built_default_tls(
|
||||||
http,
|
http, tls, proxies, user_agent, local_addr, nodelay,
|
||||||
tls,
|
|
||||||
proxies,
|
|
||||||
user_agent,
|
|
||||||
local_addr,
|
|
||||||
nodelay,
|
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "default-tls")]
|
#[cfg(feature = "default-tls")]
|
||||||
pub(crate) fn from_built_default_tls<T> (
|
pub(crate) fn from_built_default_tls<T>(
|
||||||
mut http: HttpConnector,
|
mut http: HttpConnector,
|
||||||
tls: TlsConnector,
|
tls: TlsConnector,
|
||||||
proxies: Arc<Vec<Proxy>>,
|
proxies: Arc<Vec<Proxy>>,
|
||||||
user_agent: Option<HeaderValue>,
|
user_agent: Option<HeaderValue>,
|
||||||
local_addr: T,
|
local_addr: T,
|
||||||
nodelay: bool) -> Connector
|
nodelay: bool,
|
||||||
where
|
) -> Connector
|
||||||
T: Into<Option<IpAddr>>,
|
where
|
||||||
|
T: Into<Option<IpAddr>>,
|
||||||
{
|
{
|
||||||
http.set_local_address(local_addr.into());
|
http.set_local_address(local_addr.into());
|
||||||
http.enforce_http(false);
|
http.enforce_http(false);
|
||||||
@@ -245,11 +241,7 @@ impl Connector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "socks")]
|
#[cfg(feature = "socks")]
|
||||||
async fn connect_socks(
|
async fn connect_socks(&self, dst: Uri, proxy: ProxyScheme) -> Result<Conn, BoxError> {
|
||||||
&self,
|
|
||||||
dst: Uri,
|
|
||||||
proxy: ProxyScheme,
|
|
||||||
) -> Result<Conn, BoxError> {
|
|
||||||
let dns = match proxy {
|
let dns = match proxy {
|
||||||
ProxyScheme::Socks5 {
|
ProxyScheme::Socks5 {
|
||||||
remote_dns: false, ..
|
remote_dns: false, ..
|
||||||
@@ -259,22 +251,17 @@ impl Connector {
|
|||||||
} => socks::DnsResolve::Proxy,
|
} => socks::DnsResolve::Proxy,
|
||||||
ProxyScheme::Http { .. } | ProxyScheme::Https { .. } => {
|
ProxyScheme::Http { .. } | ProxyScheme::Https { .. } => {
|
||||||
unreachable!("connect_socks is only called for socks proxies");
|
unreachable!("connect_socks is only called for socks proxies");
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
match &self.inner {
|
match &self.inner {
|
||||||
#[cfg(feature = "default-tls")]
|
#[cfg(feature = "default-tls")]
|
||||||
Inner::DefaultTls(_http, tls) => {
|
Inner::DefaultTls(_http, tls) => {
|
||||||
if dst.scheme() == Some(&Scheme::HTTPS) {
|
if dst.scheme() == Some(&Scheme::HTTPS) {
|
||||||
let host = dst
|
let host = dst.host().ok_or("no host in url")?.to_string();
|
||||||
.host()
|
|
||||||
.ok_or("no host in url")?
|
|
||||||
.to_string();
|
|
||||||
let conn = socks::connect(proxy, dst, dns).await?;
|
let conn = socks::connect(proxy, dst, dns).await?;
|
||||||
let tls_connector = tokio_native_tls::TlsConnector::from(tls.clone());
|
let tls_connector = tokio_native_tls::TlsConnector::from(tls.clone());
|
||||||
let io = tls_connector
|
let io = tls_connector.connect(&host, conn).await?;
|
||||||
.connect(&host, conn)
|
|
||||||
.await?;
|
|
||||||
return Ok(Conn {
|
return Ok(Conn {
|
||||||
inner: self.verbose.wrap(NativeTlsConn { inner: io }),
|
inner: self.verbose.wrap(NativeTlsConn { inner: io }),
|
||||||
is_proxy: false,
|
is_proxy: false,
|
||||||
@@ -288,10 +275,7 @@ impl Connector {
|
|||||||
use tokio_rustls::TlsConnector as RustlsConnector;
|
use tokio_rustls::TlsConnector as RustlsConnector;
|
||||||
|
|
||||||
let tls = tls_proxy.clone();
|
let tls = tls_proxy.clone();
|
||||||
let host = dst
|
let host = dst.host().ok_or("no host in url")?.to_string();
|
||||||
.host()
|
|
||||||
.ok_or("no host in url")?
|
|
||||||
.to_string();
|
|
||||||
let conn = socks::connect(proxy, dst, dns).await?;
|
let conn = socks::connect(proxy, dst, dns).await?;
|
||||||
let dnsname = DNSNameRef::try_from_ascii_str(&host)
|
let dnsname = DNSNameRef::try_from_ascii_str(&host)
|
||||||
.map(|dnsname| dnsname.to_owned())
|
.map(|dnsname| dnsname.to_owned())
|
||||||
@@ -306,7 +290,7 @@ impl Connector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "__tls"))]
|
#[cfg(not(feature = "__tls"))]
|
||||||
Inner::Http(_) => ()
|
Inner::Http(_) => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
socks::connect(proxy, dst, dns).await.map(|tcp| Conn {
|
socks::connect(proxy, dst, dns).await.map(|tcp| Conn {
|
||||||
@@ -315,11 +299,7 @@ impl Connector {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn connect_with_maybe_proxy(
|
async fn connect_with_maybe_proxy(self, dst: Uri, is_proxy: bool) -> Result<Conn, BoxError> {
|
||||||
self,
|
|
||||||
dst: Uri,
|
|
||||||
is_proxy: bool,
|
|
||||||
) -> Result<Conn, BoxError> {
|
|
||||||
match self.inner {
|
match self.inner {
|
||||||
#[cfg(not(feature = "__tls"))]
|
#[cfg(not(feature = "__tls"))]
|
||||||
Inner::Http(mut http) => {
|
Inner::Http(mut http) => {
|
||||||
@@ -333,7 +313,6 @@ impl Connector {
|
|||||||
Inner::DefaultTls(http, tls) => {
|
Inner::DefaultTls(http, tls) => {
|
||||||
let mut http = http.clone();
|
let mut http = http.clone();
|
||||||
|
|
||||||
|
|
||||||
// Disable Nagle's algorithm for TLS handshake
|
// Disable Nagle's algorithm for TLS handshake
|
||||||
//
|
//
|
||||||
// https://www.openssl.org/docs/man1.1.1/man3/SSL_connect.html#NOTES
|
// https://www.openssl.org/docs/man1.1.1/man3/SSL_connect.html#NOTES
|
||||||
@@ -403,7 +382,6 @@ impl Connector {
|
|||||||
ProxyScheme::Socks5 { .. } => return self.connect_socks(dst, proxy_scheme).await,
|
ProxyScheme::Socks5 { .. } => return self.connect_socks(dst, proxy_scheme).await,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#[cfg(feature = "__tls")]
|
#[cfg(feature = "__tls")]
|
||||||
let auth = _auth;
|
let auth = _auth;
|
||||||
|
|
||||||
@@ -420,13 +398,12 @@ impl Connector {
|
|||||||
log::trace!("tunneling HTTPS over proxy");
|
log::trace!("tunneling HTTPS over proxy");
|
||||||
let tunneled = tunnel(
|
let tunneled = tunnel(
|
||||||
conn,
|
conn,
|
||||||
host
|
host.ok_or("no host in url")?.to_string(),
|
||||||
.ok_or("no host in url")?
|
|
||||||
.to_string(),
|
|
||||||
port,
|
port,
|
||||||
self.user_agent.clone(),
|
self.user_agent.clone(),
|
||||||
auth
|
auth,
|
||||||
).await?;
|
)
|
||||||
|
.await?;
|
||||||
let tls_connector = tokio_native_tls::TlsConnector::from(tls.clone());
|
let tls_connector = tokio_native_tls::TlsConnector::from(tls.clone());
|
||||||
let io = tls_connector
|
let io = tls_connector
|
||||||
.connect(&host.ok_or("no host in url")?, tunneled)
|
.connect(&host.ok_or("no host in url")?, tunneled)
|
||||||
@@ -447,10 +424,7 @@ impl Connector {
|
|||||||
use tokio_rustls::webpki::DNSNameRef;
|
use tokio_rustls::webpki::DNSNameRef;
|
||||||
use tokio_rustls::TlsConnector as RustlsConnector;
|
use tokio_rustls::TlsConnector as RustlsConnector;
|
||||||
|
|
||||||
let host = dst
|
let host = dst.host().ok_or("no host in url")?.to_string();
|
||||||
.host()
|
|
||||||
.ok_or("no host in url")?
|
|
||||||
.to_string();
|
|
||||||
let port = dst.port().map(|r| r.as_u16()).unwrap_or(443);
|
let port = dst.port().map(|r| r.as_u16()).unwrap_or(443);
|
||||||
let http = http.clone();
|
let http = http.clone();
|
||||||
let mut http = hyper_rustls::HttpsConnector::from((http, tls_proxy.clone()));
|
let mut http = hyper_rustls::HttpsConnector::from((http, tls_proxy.clone()));
|
||||||
@@ -544,7 +518,10 @@ impl Service<Uri> for Connector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) trait AsyncConn: AsyncRead + AsyncWrite + Connection + Send + Sync + Unpin + 'static {}
|
pub(crate) trait AsyncConn:
|
||||||
|
AsyncRead + AsyncWrite + Connection + Send + Sync + Unpin + 'static
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: AsyncRead + AsyncWrite + Connection + Send + Sync + Unpin + 'static> AsyncConn for T {}
|
impl<T: AsyncRead + AsyncWrite + Connection + Send + Sync + Unpin + 'static> AsyncConn for T {}
|
||||||
|
|
||||||
@@ -572,7 +549,7 @@ impl AsyncRead for Conn {
|
|||||||
fn poll_read(
|
fn poll_read(
|
||||||
self: Pin<&mut Self>,
|
self: Pin<&mut Self>,
|
||||||
cx: &mut Context,
|
cx: &mut Context,
|
||||||
buf: &mut ReadBuf<'_>
|
buf: &mut ReadBuf<'_>,
|
||||||
) -> Poll<io::Result<()>> {
|
) -> Poll<io::Result<()>> {
|
||||||
let this = self.project();
|
let this = self.project();
|
||||||
AsyncRead::poll_read(this.inner, cx, buf)
|
AsyncRead::poll_read(this.inner, cx, buf)
|
||||||
@@ -583,7 +560,7 @@ impl AsyncWrite for Conn {
|
|||||||
fn poll_write(
|
fn poll_write(
|
||||||
self: Pin<&mut Self>,
|
self: Pin<&mut Self>,
|
||||||
cx: &mut Context,
|
cx: &mut Context,
|
||||||
buf: &[u8]
|
buf: &[u8],
|
||||||
) -> Poll<Result<usize, io::Error>> {
|
) -> Poll<Result<usize, io::Error>> {
|
||||||
let this = self.project();
|
let this = self.project();
|
||||||
AsyncWrite::poll_write(this.inner, cx, buf)
|
AsyncWrite::poll_write(this.inner, cx, buf)
|
||||||
@@ -592,7 +569,7 @@ impl AsyncWrite for Conn {
|
|||||||
fn poll_write_vectored(
|
fn poll_write_vectored(
|
||||||
self: Pin<&mut Self>,
|
self: Pin<&mut Self>,
|
||||||
cx: &mut Context<'_>,
|
cx: &mut Context<'_>,
|
||||||
bufs: &[IoSlice<'_>]
|
bufs: &[IoSlice<'_>],
|
||||||
) -> Poll<Result<usize, io::Error>> {
|
) -> Poll<Result<usize, io::Error>> {
|
||||||
let this = self.project();
|
let this = self.project();
|
||||||
AsyncWrite::poll_write_vectored(this.inner, cx, bufs)
|
AsyncWrite::poll_write_vectored(this.inner, cx, bufs)
|
||||||
@@ -607,17 +584,13 @@ impl AsyncWrite for Conn {
|
|||||||
AsyncWrite::poll_flush(this.inner, cx)
|
AsyncWrite::poll_flush(this.inner, cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn poll_shutdown(
|
fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), io::Error>> {
|
||||||
self: Pin<&mut Self>,
|
|
||||||
cx: &mut Context
|
|
||||||
) -> Poll<Result<(), io::Error>> {
|
|
||||||
let this = self.project();
|
let this = self.project();
|
||||||
AsyncWrite::poll_shutdown(this.inner, cx)
|
AsyncWrite::poll_shutdown(this.inner, cx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) type Connecting =
|
pub(crate) type Connecting = Pin<Box<dyn Future<Output = Result<Conn, BoxError>> + Send>>;
|
||||||
Pin<Box<dyn Future<Output = Result<Conn, BoxError>> + Send>>;
|
|
||||||
|
|
||||||
#[cfg(feature = "__tls")]
|
#[cfg(feature = "__tls")]
|
||||||
async fn tunnel<T>(
|
async fn tunnel<T>(
|
||||||
@@ -641,7 +614,6 @@ where
|
|||||||
)
|
)
|
||||||
.into_bytes();
|
.into_bytes();
|
||||||
|
|
||||||
|
|
||||||
// user-agent
|
// user-agent
|
||||||
if let Some(user_agent) = user_agent {
|
if let Some(user_agent) = user_agent {
|
||||||
buf.extend_from_slice(b"User-Agent: ");
|
buf.extend_from_slice(b"User-Agent: ");
|
||||||
@@ -649,7 +621,6 @@ where
|
|||||||
buf.extend_from_slice(b"\r\n");
|
buf.extend_from_slice(b"\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// proxy-authorization
|
// proxy-authorization
|
||||||
if let Some(value) = auth {
|
if let Some(value) = auth {
|
||||||
log::debug!("tunnel to {}:{} using basic auth", host, port);
|
log::debug!("tunnel to {}:{} using basic auth", host, port);
|
||||||
@@ -680,15 +651,11 @@ where
|
|||||||
return Ok(conn);
|
return Ok(conn);
|
||||||
}
|
}
|
||||||
if pos == buf.len() {
|
if pos == buf.len() {
|
||||||
return Err(
|
return Err("proxy headers too long for tunnel".into());
|
||||||
"proxy headers too long for tunnel".into()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
// else read more
|
// else read more
|
||||||
} else if recvd.starts_with(b"HTTP/1.1 407") {
|
} else if recvd.starts_with(b"HTTP/1.1 407") {
|
||||||
return Err(
|
return Err("proxy authentication required".into());
|
||||||
"proxy authentication required".into()
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
return Err("unsuccessful tunnel".into());
|
return Err("unsuccessful tunnel".into());
|
||||||
}
|
}
|
||||||
@@ -702,13 +669,16 @@ fn tunnel_eof() -> BoxError {
|
|||||||
|
|
||||||
#[cfg(feature = "default-tls")]
|
#[cfg(feature = "default-tls")]
|
||||||
mod native_tls_conn {
|
mod native_tls_conn {
|
||||||
use std::{pin::Pin, task::{Context, Poll}, io::{self, IoSlice}};
|
|
||||||
use hyper::client::connect::{Connected, Connection};
|
use hyper::client::connect::{Connected, Connection};
|
||||||
use pin_project_lite::pin_project;
|
use pin_project_lite::pin_project;
|
||||||
|
use std::{
|
||||||
|
io::{self, IoSlice},
|
||||||
|
pin::Pin,
|
||||||
|
task::{Context, Poll},
|
||||||
|
};
|
||||||
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
|
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
|
||||||
use tokio_native_tls::TlsStream;
|
use tokio_native_tls::TlsStream;
|
||||||
|
|
||||||
|
|
||||||
pin_project! {
|
pin_project! {
|
||||||
pub(super) struct NativeTlsConn<T> {
|
pub(super) struct NativeTlsConn<T> {
|
||||||
#[pin] pub(super) inner: TlsStream<T>,
|
#[pin] pub(super) inner: TlsStream<T>,
|
||||||
@@ -725,7 +695,7 @@ mod native_tls_conn {
|
|||||||
fn poll_read(
|
fn poll_read(
|
||||||
self: Pin<&mut Self>,
|
self: Pin<&mut Self>,
|
||||||
cx: &mut Context,
|
cx: &mut Context,
|
||||||
buf: &mut ReadBuf<'_>
|
buf: &mut ReadBuf<'_>,
|
||||||
) -> Poll<tokio::io::Result<()>> {
|
) -> Poll<tokio::io::Result<()>> {
|
||||||
let this = self.project();
|
let this = self.project();
|
||||||
AsyncRead::poll_read(this.inner, cx, buf)
|
AsyncRead::poll_read(this.inner, cx, buf)
|
||||||
@@ -736,7 +706,7 @@ mod native_tls_conn {
|
|||||||
fn poll_write(
|
fn poll_write(
|
||||||
self: Pin<&mut Self>,
|
self: Pin<&mut Self>,
|
||||||
cx: &mut Context,
|
cx: &mut Context,
|
||||||
buf: &[u8]
|
buf: &[u8],
|
||||||
) -> Poll<Result<usize, tokio::io::Error>> {
|
) -> Poll<Result<usize, tokio::io::Error>> {
|
||||||
let this = self.project();
|
let this = self.project();
|
||||||
AsyncWrite::poll_write(this.inner, cx, buf)
|
AsyncWrite::poll_write(this.inner, cx, buf)
|
||||||
@@ -745,7 +715,7 @@ mod native_tls_conn {
|
|||||||
fn poll_write_vectored(
|
fn poll_write_vectored(
|
||||||
self: Pin<&mut Self>,
|
self: Pin<&mut Self>,
|
||||||
cx: &mut Context<'_>,
|
cx: &mut Context<'_>,
|
||||||
bufs: &[IoSlice<'_>]
|
bufs: &[IoSlice<'_>],
|
||||||
) -> Poll<Result<usize, io::Error>> {
|
) -> Poll<Result<usize, io::Error>> {
|
||||||
let this = self.project();
|
let this = self.project();
|
||||||
AsyncWrite::poll_write_vectored(this.inner, cx, bufs)
|
AsyncWrite::poll_write_vectored(this.inner, cx, bufs)
|
||||||
@@ -755,14 +725,17 @@ mod native_tls_conn {
|
|||||||
self.inner.is_write_vectored()
|
self.inner.is_write_vectored()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), tokio::io::Error>> {
|
fn poll_flush(
|
||||||
|
self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context,
|
||||||
|
) -> Poll<Result<(), tokio::io::Error>> {
|
||||||
let this = self.project();
|
let this = self.project();
|
||||||
AsyncWrite::poll_flush(this.inner, cx)
|
AsyncWrite::poll_flush(this.inner, cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn poll_shutdown(
|
fn poll_shutdown(
|
||||||
self: Pin<&mut Self>,
|
self: Pin<&mut Self>,
|
||||||
cx: &mut Context
|
cx: &mut Context,
|
||||||
) -> Poll<Result<(), tokio::io::Error>> {
|
) -> Poll<Result<(), tokio::io::Error>> {
|
||||||
let this = self.project();
|
let this = self.project();
|
||||||
AsyncWrite::poll_shutdown(this.inner, cx)
|
AsyncWrite::poll_shutdown(this.inner, cx)
|
||||||
@@ -772,14 +745,17 @@ mod native_tls_conn {
|
|||||||
|
|
||||||
#[cfg(feature = "__rustls")]
|
#[cfg(feature = "__rustls")]
|
||||||
mod rustls_tls_conn {
|
mod rustls_tls_conn {
|
||||||
use rustls::Session;
|
|
||||||
use std::{pin::Pin, task::{Context, Poll}, io::{self, IoSlice}};
|
|
||||||
use hyper::client::connect::{Connected, Connection};
|
use hyper::client::connect::{Connected, Connection};
|
||||||
use pin_project_lite::pin_project;
|
use pin_project_lite::pin_project;
|
||||||
|
use rustls::Session;
|
||||||
|
use std::{
|
||||||
|
io::{self, IoSlice},
|
||||||
|
pin::Pin,
|
||||||
|
task::{Context, Poll},
|
||||||
|
};
|
||||||
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
|
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
|
||||||
use tokio_rustls::client::TlsStream;
|
use tokio_rustls::client::TlsStream;
|
||||||
|
|
||||||
|
|
||||||
pin_project! {
|
pin_project! {
|
||||||
pub(super) struct RustlsTlsConn<T> {
|
pub(super) struct RustlsTlsConn<T> {
|
||||||
#[pin] pub(super) inner: TlsStream<T>,
|
#[pin] pub(super) inner: TlsStream<T>,
|
||||||
@@ -800,7 +776,7 @@ mod rustls_tls_conn {
|
|||||||
fn poll_read(
|
fn poll_read(
|
||||||
self: Pin<&mut Self>,
|
self: Pin<&mut Self>,
|
||||||
cx: &mut Context,
|
cx: &mut Context,
|
||||||
buf: &mut ReadBuf<'_>
|
buf: &mut ReadBuf<'_>,
|
||||||
) -> Poll<tokio::io::Result<()>> {
|
) -> Poll<tokio::io::Result<()>> {
|
||||||
let this = self.project();
|
let this = self.project();
|
||||||
AsyncRead::poll_read(this.inner, cx, buf)
|
AsyncRead::poll_read(this.inner, cx, buf)
|
||||||
@@ -811,7 +787,7 @@ mod rustls_tls_conn {
|
|||||||
fn poll_write(
|
fn poll_write(
|
||||||
self: Pin<&mut Self>,
|
self: Pin<&mut Self>,
|
||||||
cx: &mut Context,
|
cx: &mut Context,
|
||||||
buf: &[u8]
|
buf: &[u8],
|
||||||
) -> Poll<Result<usize, tokio::io::Error>> {
|
) -> Poll<Result<usize, tokio::io::Error>> {
|
||||||
let this = self.project();
|
let this = self.project();
|
||||||
AsyncWrite::poll_write(this.inner, cx, buf)
|
AsyncWrite::poll_write(this.inner, cx, buf)
|
||||||
@@ -820,7 +796,7 @@ mod rustls_tls_conn {
|
|||||||
fn poll_write_vectored(
|
fn poll_write_vectored(
|
||||||
self: Pin<&mut Self>,
|
self: Pin<&mut Self>,
|
||||||
cx: &mut Context<'_>,
|
cx: &mut Context<'_>,
|
||||||
bufs: &[IoSlice<'_>]
|
bufs: &[IoSlice<'_>],
|
||||||
) -> Poll<Result<usize, io::Error>> {
|
) -> Poll<Result<usize, io::Error>> {
|
||||||
let this = self.project();
|
let this = self.project();
|
||||||
AsyncWrite::poll_write_vectored(this.inner, cx, bufs)
|
AsyncWrite::poll_write_vectored(this.inner, cx, bufs)
|
||||||
@@ -830,14 +806,17 @@ mod rustls_tls_conn {
|
|||||||
self.inner.is_write_vectored()
|
self.inner.is_write_vectored()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), tokio::io::Error>> {
|
fn poll_flush(
|
||||||
|
self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context,
|
||||||
|
) -> Poll<Result<(), tokio::io::Error>> {
|
||||||
let this = self.project();
|
let this = self.project();
|
||||||
AsyncWrite::poll_flush(this.inner, cx)
|
AsyncWrite::poll_flush(this.inner, cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn poll_shutdown(
|
fn poll_shutdown(
|
||||||
self: Pin<&mut Self>,
|
self: Pin<&mut Self>,
|
||||||
cx: &mut Context
|
cx: &mut Context,
|
||||||
) -> Poll<Result<(), tokio::io::Error>> {
|
) -> Poll<Result<(), tokio::io::Error>> {
|
||||||
let this = self.project();
|
let this = self.project();
|
||||||
AsyncWrite::poll_shutdown(this.inner, cx)
|
AsyncWrite::poll_shutdown(this.inner, cx)
|
||||||
@@ -911,11 +890,11 @@ mod socks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mod verbose {
|
mod verbose {
|
||||||
|
use hyper::client::connect::{Connected, Connection};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::io::{self, IoSlice};
|
use std::io::{self, IoSlice};
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::task::{Context, Poll};
|
use std::task::{Context, Poll};
|
||||||
use hyper::client::connect::{Connected, Connection};
|
|
||||||
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
|
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
|
||||||
|
|
||||||
pub(super) const OFF: Wrapper = Wrapper(false);
|
pub(super) const OFF: Wrapper = Wrapper(false);
|
||||||
@@ -952,16 +931,14 @@ mod verbose {
|
|||||||
fn poll_read(
|
fn poll_read(
|
||||||
mut self: Pin<&mut Self>,
|
mut self: Pin<&mut Self>,
|
||||||
cx: &mut Context,
|
cx: &mut Context,
|
||||||
buf: &mut ReadBuf<'_>
|
buf: &mut ReadBuf<'_>,
|
||||||
) -> Poll<std::io::Result<()>> {
|
) -> Poll<std::io::Result<()>> {
|
||||||
match Pin::new(&mut self.inner).poll_read(cx, buf) {
|
match Pin::new(&mut self.inner).poll_read(cx, buf) {
|
||||||
Poll::Ready(Ok(())) => {
|
Poll::Ready(Ok(())) => {
|
||||||
log::trace!("{:08x} read: {:?}", self.id, Escape(buf.filled()));
|
log::trace!("{:08x} read: {:?}", self.id, Escape(buf.filled()));
|
||||||
Poll::Ready(Ok(()))
|
Poll::Ready(Ok(()))
|
||||||
},
|
}
|
||||||
Poll::Ready(Err(e)) => {
|
Poll::Ready(Err(e)) => Poll::Ready(Err(e)),
|
||||||
Poll::Ready(Err(e))
|
|
||||||
},
|
|
||||||
Poll::Pending => Poll::Pending,
|
Poll::Pending => Poll::Pending,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -971,16 +948,14 @@ mod verbose {
|
|||||||
fn poll_write(
|
fn poll_write(
|
||||||
mut self: Pin<&mut Self>,
|
mut self: Pin<&mut Self>,
|
||||||
cx: &mut Context,
|
cx: &mut Context,
|
||||||
buf: &[u8]
|
buf: &[u8],
|
||||||
) -> Poll<Result<usize, std::io::Error>> {
|
) -> Poll<Result<usize, std::io::Error>> {
|
||||||
match Pin::new(&mut self.inner).poll_write(cx, buf) {
|
match Pin::new(&mut self.inner).poll_write(cx, buf) {
|
||||||
Poll::Ready(Ok(n)) => {
|
Poll::Ready(Ok(n)) => {
|
||||||
log::trace!("{:08x} write: {:?}", self.id, Escape(&buf[..n]));
|
log::trace!("{:08x} write: {:?}", self.id, Escape(&buf[..n]));
|
||||||
Poll::Ready(Ok(n))
|
Poll::Ready(Ok(n))
|
||||||
},
|
}
|
||||||
Poll::Ready(Err(e)) => {
|
Poll::Ready(Err(e)) => Poll::Ready(Err(e)),
|
||||||
Poll::Ready(Err(e))
|
|
||||||
},
|
|
||||||
Poll::Pending => Poll::Pending,
|
Poll::Pending => Poll::Pending,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -988,7 +963,7 @@ mod verbose {
|
|||||||
fn poll_write_vectored(
|
fn poll_write_vectored(
|
||||||
mut self: Pin<&mut Self>,
|
mut self: Pin<&mut Self>,
|
||||||
cx: &mut Context<'_>,
|
cx: &mut Context<'_>,
|
||||||
bufs: &[IoSlice<'_>]
|
bufs: &[IoSlice<'_>],
|
||||||
) -> Poll<Result<usize, io::Error>> {
|
) -> Poll<Result<usize, io::Error>> {
|
||||||
Pin::new(&mut self.inner).poll_write_vectored(cx, bufs)
|
Pin::new(&mut self.inner).poll_write_vectored(cx, bufs)
|
||||||
}
|
}
|
||||||
@@ -997,13 +972,16 @@ mod verbose {
|
|||||||
self.inner.is_write_vectored()
|
self.inner.is_write_vectored()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), std::io::Error>> {
|
fn poll_flush(
|
||||||
|
mut self: Pin<&mut Self>,
|
||||||
|
cx: &mut Context,
|
||||||
|
) -> Poll<Result<(), std::io::Error>> {
|
||||||
Pin::new(&mut self.inner).poll_flush(cx)
|
Pin::new(&mut self.inner).poll_flush(cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn poll_shutdown(
|
fn poll_shutdown(
|
||||||
mut self: Pin<&mut Self>,
|
mut self: Pin<&mut Self>,
|
||||||
cx: &mut Context
|
cx: &mut Context,
|
||||||
) -> Poll<Result<(), std::io::Error>> {
|
) -> Poll<Result<(), std::io::Error>> {
|
||||||
Pin::new(&mut self.inner).poll_shutdown(cx)
|
Pin::new(&mut self.inner).poll_shutdown(cx)
|
||||||
}
|
}
|
||||||
@@ -1101,7 +1079,10 @@ mod tests {
|
|||||||
fn test_tunnel() {
|
fn test_tunnel() {
|
||||||
let addr = mock_tunnel!();
|
let addr = mock_tunnel!();
|
||||||
|
|
||||||
let rt = runtime::Builder::new_current_thread().enable_all().build().expect("new rt");
|
let rt = runtime::Builder::new_current_thread()
|
||||||
|
.enable_all()
|
||||||
|
.build()
|
||||||
|
.expect("new rt");
|
||||||
let f = async move {
|
let f = async move {
|
||||||
let tcp = TcpStream::connect(&addr).await?;
|
let tcp = TcpStream::connect(&addr).await?;
|
||||||
let host = addr.ip().to_string();
|
let host = addr.ip().to_string();
|
||||||
@@ -1116,7 +1097,10 @@ mod tests {
|
|||||||
fn test_tunnel_eof() {
|
fn test_tunnel_eof() {
|
||||||
let addr = mock_tunnel!(b"HTTP/1.1 200 OK");
|
let addr = mock_tunnel!(b"HTTP/1.1 200 OK");
|
||||||
|
|
||||||
let rt = runtime::Builder::new_current_thread().enable_all().build().expect("new rt");
|
let rt = runtime::Builder::new_current_thread()
|
||||||
|
.enable_all()
|
||||||
|
.build()
|
||||||
|
.expect("new rt");
|
||||||
let f = async move {
|
let f = async move {
|
||||||
let tcp = TcpStream::connect(&addr).await?;
|
let tcp = TcpStream::connect(&addr).await?;
|
||||||
let host = addr.ip().to_string();
|
let host = addr.ip().to_string();
|
||||||
@@ -1131,7 +1115,10 @@ mod tests {
|
|||||||
fn test_tunnel_non_http_response() {
|
fn test_tunnel_non_http_response() {
|
||||||
let addr = mock_tunnel!(b"foo bar baz hallo");
|
let addr = mock_tunnel!(b"foo bar baz hallo");
|
||||||
|
|
||||||
let rt = runtime::Builder::new_current_thread().enable_all().build().expect("new rt");
|
let rt = runtime::Builder::new_current_thread()
|
||||||
|
.enable_all()
|
||||||
|
.build()
|
||||||
|
.expect("new rt");
|
||||||
let f = async move {
|
let f = async move {
|
||||||
let tcp = TcpStream::connect(&addr).await?;
|
let tcp = TcpStream::connect(&addr).await?;
|
||||||
let host = addr.ip().to_string();
|
let host = addr.ip().to_string();
|
||||||
@@ -1152,7 +1139,10 @@ mod tests {
|
|||||||
"
|
"
|
||||||
);
|
);
|
||||||
|
|
||||||
let rt = runtime::Builder::new_current_thread().enable_all().build().expect("new rt");
|
let rt = runtime::Builder::new_current_thread()
|
||||||
|
.enable_all()
|
||||||
|
.build()
|
||||||
|
.expect("new rt");
|
||||||
let f = async move {
|
let f = async move {
|
||||||
let tcp = TcpStream::connect(&addr).await?;
|
let tcp = TcpStream::connect(&addr).await?;
|
||||||
let host = addr.ip().to_string();
|
let host = addr.ip().to_string();
|
||||||
@@ -1171,7 +1161,10 @@ mod tests {
|
|||||||
"Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==\r\n"
|
"Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==\r\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
let rt = runtime::Builder::new_current_thread().enable_all().build().expect("new rt");
|
let rt = runtime::Builder::new_current_thread()
|
||||||
|
.enable_all()
|
||||||
|
.build()
|
||||||
|
.expect("new rt");
|
||||||
let f = async move {
|
let f = async move {
|
||||||
let tcp = TcpStream::connect(&addr).await?;
|
let tcp = TcpStream::connect(&addr).await?;
|
||||||
let host = addr.ip().to_string();
|
let host = addr.ip().to_string();
|
||||||
|
|||||||
@@ -64,9 +64,10 @@ impl<'a> Cookie<'a> {
|
|||||||
|
|
||||||
/// Get the Max-Age information.
|
/// Get the Max-Age information.
|
||||||
pub fn max_age(&self) -> Option<std::time::Duration> {
|
pub fn max_age(&self) -> Option<std::time::Duration> {
|
||||||
self.0
|
self.0.max_age().map(|d| {
|
||||||
.max_age()
|
d.try_into()
|
||||||
.map(|d| d.try_into().expect("time::Duration into std::time::Duration"))
|
.expect("time::Duration into std::time::Duration")
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The cookie expiration time.
|
/// The cookie expiration time.
|
||||||
|
|||||||
15
src/dns.rs
15
src/dns.rs
@@ -1,9 +1,9 @@
|
|||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
|
use std::io;
|
||||||
|
use std::net::SocketAddr;
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::task::{self, Poll};
|
use std::task::{self, Poll};
|
||||||
use std::io;
|
|
||||||
use std::net::SocketAddr;
|
|
||||||
|
|
||||||
use hyper::client::connect::dns as hyper_dns;
|
use hyper::client::connect::dns as hyper_dns;
|
||||||
use hyper::service::Service;
|
use hyper::service::Service;
|
||||||
@@ -11,7 +11,7 @@ use tokio::sync::Mutex;
|
|||||||
use trust_dns_resolver::{
|
use trust_dns_resolver::{
|
||||||
config::{ResolverConfig, ResolverOpts},
|
config::{ResolverConfig, ResolverOpts},
|
||||||
lookup_ip::LookupIpIntoIter,
|
lookup_ip::LookupIpIntoIter,
|
||||||
system_conf, AsyncResolver, TokioConnection, TokioConnectionProvider, TokioHandle
|
system_conf, AsyncResolver, TokioConnection, TokioConnectionProvider, TokioHandle,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::error::BoxError;
|
use crate::error::BoxError;
|
||||||
@@ -19,7 +19,8 @@ use crate::error::BoxError;
|
|||||||
type SharedResolver = Arc<AsyncResolver<TokioConnection, TokioConnectionProvider>>;
|
type SharedResolver = Arc<AsyncResolver<TokioConnection, TokioConnectionProvider>>;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref SYSTEM_CONF: io::Result<(ResolverConfig, ResolverOpts)> = system_conf::read_system_conf().map_err(io::Error::from);
|
static ref SYSTEM_CONF: io::Result<(ResolverConfig, ResolverOpts)> =
|
||||||
|
system_conf::read_system_conf().map_err(io::Error::from);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@@ -70,7 +71,7 @@ impl Service<hyper_dns::Name> for TrustDnsResolver {
|
|||||||
let resolver = new_resolver().await?;
|
let resolver = new_resolver().await?;
|
||||||
*lock = State::Ready(resolver.clone());
|
*lock = State::Ready(resolver.clone());
|
||||||
resolver
|
resolver
|
||||||
},
|
}
|
||||||
State::Ready(resolver) => resolver.clone(),
|
State::Ready(resolver) => resolver.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -79,7 +80,9 @@ impl Service<hyper_dns::Name> for TrustDnsResolver {
|
|||||||
drop(lock);
|
drop(lock);
|
||||||
|
|
||||||
let lookup = resolver.lookup_ip(name.as_str()).await?;
|
let lookup = resolver.lookup_ip(name.as_str()).await?;
|
||||||
Ok(SocketAddrs { iter: lookup.into_iter() })
|
Ok(SocketAddrs {
|
||||||
|
iter: lookup.into_iter(),
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -267,7 +267,6 @@ fn test_redirect_policy_limit() {
|
|||||||
.map(|i| Url::parse(&format!("http://a.b/c/{}", i)).unwrap())
|
.map(|i| Url::parse(&format!("http://a.b/c/{}", i)).unwrap())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
|
||||||
match policy.check(StatusCode::FOUND, &next, &previous) {
|
match policy.check(StatusCode::FOUND, &next, &previous) {
|
||||||
ActionKind::Follow => (),
|
ActionKind::Follow => (),
|
||||||
other => panic!("unexpected {:?}", other),
|
other => panic!("unexpected {:?}", other),
|
||||||
@@ -298,7 +297,7 @@ fn test_redirect_policy_custom() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let next = Url::parse("http://foo/baz").unwrap();
|
let next = Url::parse("http://foo/baz").unwrap();
|
||||||
match policy.check(StatusCode::FOUND, &next, &[]) {
|
match policy.check(StatusCode::FOUND, &next, &[]) {
|
||||||
ActionKind::Stop => (),
|
ActionKind::Stop => (),
|
||||||
other => panic!("unexpected {:?}", other),
|
other => panic!("unexpected {:?}", other),
|
||||||
}
|
}
|
||||||
|
|||||||
21
src/tls.rs
21
src/tls.rs
@@ -22,10 +22,7 @@ enum Cert {
|
|||||||
|
|
||||||
/// Represents a private key and X509 cert as a client certificate.
|
/// Represents a private key and X509 cert as a client certificate.
|
||||||
pub struct Identity {
|
pub struct Identity {
|
||||||
#[cfg_attr(
|
#[cfg_attr(not(any(feature = "native-tls", feature = "__rustls")), allow(unused))]
|
||||||
not(any(feature = "native-tls", feature = "__rustls")),
|
|
||||||
allow(unused)
|
|
||||||
)]
|
|
||||||
inner: ClientCert,
|
inner: ClientCert,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,7 +156,8 @@ impl Identity {
|
|||||||
pub fn from_pkcs12_der(der: &[u8], password: &str) -> crate::Result<Identity> {
|
pub fn from_pkcs12_der(der: &[u8], password: &str) -> crate::Result<Identity> {
|
||||||
Ok(Identity {
|
Ok(Identity {
|
||||||
inner: ClientCert::Pkcs12(
|
inner: ClientCert::Pkcs12(
|
||||||
native_tls_crate::Identity::from_pkcs12(der, password).map_err(crate::error::builder)?,
|
native_tls_crate::Identity::from_pkcs12(der, password)
|
||||||
|
.map_err(crate::error::builder)?,
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -245,7 +243,8 @@ impl Identity {
|
|||||||
pub(crate) fn add_to_rustls(self, tls: &mut rustls::ClientConfig) -> crate::Result<()> {
|
pub(crate) fn add_to_rustls(self, tls: &mut rustls::ClientConfig) -> crate::Result<()> {
|
||||||
match self.inner {
|
match self.inner {
|
||||||
ClientCert::Pem { key, certs } => {
|
ClientCert::Pem { key, certs } => {
|
||||||
tls.set_single_client_cert(certs, key).map_err(|e| crate::error::builder(e))?;
|
tls.set_single_client_cert(certs, key)
|
||||||
|
.map_err(|e| crate::error::builder(e))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
#[cfg(feature = "native-tls")]
|
#[cfg(feature = "native-tls")]
|
||||||
@@ -275,10 +274,7 @@ pub(crate) enum TlsBackend {
|
|||||||
Rustls,
|
Rustls,
|
||||||
#[cfg(feature = "__rustls")]
|
#[cfg(feature = "__rustls")]
|
||||||
BuiltRustls(rustls::ClientConfig),
|
BuiltRustls(rustls::ClientConfig),
|
||||||
#[cfg(any(
|
#[cfg(any(feature = "native-tls", feature = "__rustls",))]
|
||||||
feature = "native-tls",
|
|
||||||
feature = "__rustls",
|
|
||||||
))]
|
|
||||||
UnknownPreconfigured,
|
UnknownPreconfigured,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,10 +289,7 @@ impl fmt::Debug for TlsBackend {
|
|||||||
TlsBackend::Rustls => write!(f, "Rustls"),
|
TlsBackend::Rustls => write!(f, "Rustls"),
|
||||||
#[cfg(feature = "__rustls")]
|
#[cfg(feature = "__rustls")]
|
||||||
TlsBackend::BuiltRustls(_) => write!(f, "BuiltRustls"),
|
TlsBackend::BuiltRustls(_) => write!(f, "BuiltRustls"),
|
||||||
#[cfg(any(
|
#[cfg(any(feature = "native-tls", feature = "__rustls",))]
|
||||||
feature = "native-tls",
|
|
||||||
feature = "__rustls",
|
|
||||||
))]
|
|
||||||
TlsBackend::UnknownPreconfigured => write!(f, "UnknownPreconfigured"),
|
TlsBackend::UnknownPreconfigured => write!(f, "UnknownPreconfigured"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
use super::multipart::Form;
|
use super::multipart::Form;
|
||||||
/// dox
|
/// dox
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use std::fmt;
|
|
||||||
use js_sys::Uint8Array;
|
use js_sys::Uint8Array;
|
||||||
|
use std::fmt;
|
||||||
use wasm_bindgen::JsValue;
|
use wasm_bindgen::JsValue;
|
||||||
|
|
||||||
/// The body of a `Request`.
|
/// The body of a `Request`.
|
||||||
|
|||||||
@@ -2,31 +2,26 @@ use wasm_bindgen::JsCast;
|
|||||||
|
|
||||||
mod body;
|
mod body;
|
||||||
mod client;
|
mod client;
|
||||||
mod request;
|
|
||||||
mod response;
|
|
||||||
/// TODO
|
/// TODO
|
||||||
#[cfg(feature = "multipart")]
|
#[cfg(feature = "multipart")]
|
||||||
pub mod multipart;
|
pub mod multipart;
|
||||||
|
mod request;
|
||||||
|
mod response;
|
||||||
|
|
||||||
pub use self::body::Body;
|
pub use self::body::Body;
|
||||||
pub use self::client::{Client, ClientBuilder};
|
pub use self::client::{Client, ClientBuilder};
|
||||||
pub use self::request::{Request, RequestBuilder};
|
pub use self::request::{Request, RequestBuilder};
|
||||||
pub use self::response::Response;
|
pub use self::response::Response;
|
||||||
|
|
||||||
|
|
||||||
async fn promise<T>(promise: js_sys::Promise) -> Result<T, crate::error::BoxError>
|
async fn promise<T>(promise: js_sys::Promise) -> Result<T, crate::error::BoxError>
|
||||||
where
|
where
|
||||||
T: JsCast,
|
T: JsCast,
|
||||||
{
|
{
|
||||||
use wasm_bindgen_futures::JsFuture;
|
use wasm_bindgen_futures::JsFuture;
|
||||||
|
|
||||||
let js_val = JsFuture::from(promise)
|
let js_val = JsFuture::from(promise).await.map_err(crate::error::wasm)?;
|
||||||
.await
|
|
||||||
.map_err(crate::error::wasm)?;
|
|
||||||
|
|
||||||
js_val
|
js_val
|
||||||
.dyn_into::<T>()
|
.dyn_into::<T>()
|
||||||
.map_err(|_js_val| {
|
.map_err(|_js_val| "promise resolved to unexpected type".into())
|
||||||
"promise resolved to unexpected type".into()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,7 +90,6 @@ impl Form {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn to_form_data(&self) -> crate::Result<FormData> {
|
pub(crate) fn to_form_data(&self) -> crate::Result<FormData> {
|
||||||
|
|
||||||
let form = FormData::new()
|
let form = FormData::new()
|
||||||
.map_err(crate::error::wasm)
|
.map_err(crate::error::wasm)
|
||||||
.map_err(crate::error::builder)?;
|
.map_err(crate::error::builder)?;
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ use std::convert::TryFrom;
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use http::{request::Parts, Method, Request as HttpRequest};
|
use http::{request::Parts, Method, Request as HttpRequest};
|
||||||
use url::Url;
|
use serde::Serialize;
|
||||||
#[cfg(feature = "json")]
|
#[cfg(feature = "json")]
|
||||||
use serde_json;
|
use serde_json;
|
||||||
use serde::Serialize;
|
|
||||||
use serde_urlencoded;
|
use serde_urlencoded;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
use super::{Body, Client, Response};
|
use super::{Body, Client, Response};
|
||||||
use crate::header::{HeaderMap, HeaderName, HeaderValue, CONTENT_TYPE};
|
use crate::header::{HeaderMap, HeaderName, HeaderValue, CONTENT_TYPE};
|
||||||
@@ -184,7 +184,6 @@ impl RequestBuilder {
|
|||||||
self.header(crate::header::AUTHORIZATION, header_value)
|
self.header(crate::header::AUTHORIZATION, header_value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Set the request body.
|
/// Set the request body.
|
||||||
pub fn body<T: Into<Body>>(mut self, body: T) -> RequestBuilder {
|
pub fn body<T: Into<Body>>(mut self, body: T) -> RequestBuilder {
|
||||||
if let Ok(ref mut req) = self.request {
|
if let Ok(ref mut req) = self.request {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use js_sys::Uint8Array;
|
|
||||||
use http::{HeaderMap, StatusCode};
|
use http::{HeaderMap, StatusCode};
|
||||||
|
use js_sys::Uint8Array;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
#[cfg(feature = "json")]
|
#[cfg(feature = "json")]
|
||||||
@@ -17,10 +17,7 @@ pub struct Response {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Response {
|
impl Response {
|
||||||
pub(super) fn new(
|
pub(super) fn new(res: http::Response<web_sys::Response>, url: Url) -> Response {
|
||||||
res: http::Response<web_sys::Response>,
|
|
||||||
url: Url,
|
|
||||||
) -> Response {
|
|
||||||
Response {
|
Response {
|
||||||
http: res,
|
http: res,
|
||||||
url: Box::new(url),
|
url: Box::new(url),
|
||||||
@@ -86,7 +83,10 @@ impl Response {
|
|||||||
|
|
||||||
/// Get the response text.
|
/// Get the response text.
|
||||||
pub async fn text(self) -> crate::Result<String> {
|
pub async fn text(self) -> crate::Result<String> {
|
||||||
let p = self.http.body().text()
|
let p = self
|
||||||
|
.http
|
||||||
|
.body()
|
||||||
|
.text()
|
||||||
.map_err(crate::error::wasm)
|
.map_err(crate::error::wasm)
|
||||||
.map_err(crate::error::decode)?;
|
.map_err(crate::error::decode)?;
|
||||||
let js_val = super::promise::<wasm_bindgen::JsValue>(p)
|
let js_val = super::promise::<wasm_bindgen::JsValue>(p)
|
||||||
@@ -101,7 +101,10 @@ impl Response {
|
|||||||
|
|
||||||
/// Get the response as bytes
|
/// Get the response as bytes
|
||||||
pub async fn bytes(self) -> crate::Result<Bytes> {
|
pub async fn bytes(self) -> crate::Result<Bytes> {
|
||||||
let p = self.http.body().array_buffer()
|
let p = self
|
||||||
|
.http
|
||||||
|
.body()
|
||||||
|
.array_buffer()
|
||||||
.map_err(crate::error::wasm)
|
.map_err(crate::error::wasm)
|
||||||
.map_err(crate::error::decode)?;
|
.map_err(crate::error::decode)?;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user