Refactor gzip and brotli bools into an Accepts struct
This commit is contained in:
@@ -28,6 +28,7 @@ use tokio::time::Delay;
|
||||
|
||||
use log::debug;
|
||||
|
||||
use super::decoder::Accepts;
|
||||
use super::request::{Request, RequestBuilder};
|
||||
use super::response::Response;
|
||||
use super::Body;
|
||||
@@ -62,8 +63,7 @@ pub struct ClientBuilder {
|
||||
|
||||
struct Config {
|
||||
// NOTE: When adding a new field, update `fmt::Debug for ClientBuilder`
|
||||
gzip: bool,
|
||||
brotli: bool,
|
||||
accepts: Accepts,
|
||||
headers: HeaderMap,
|
||||
#[cfg(feature = "native-tls")]
|
||||
hostname_verification: bool,
|
||||
@@ -112,8 +112,7 @@ impl ClientBuilder {
|
||||
ClientBuilder {
|
||||
config: Config {
|
||||
error: None,
|
||||
gzip: cfg!(feature = "gzip"),
|
||||
brotli: cfg!(feature = "brotli"),
|
||||
accepts: Accepts::default(),
|
||||
headers,
|
||||
#[cfg(feature = "native-tls")]
|
||||
hostname_verification: true,
|
||||
@@ -312,10 +311,9 @@ impl ClientBuilder {
|
||||
|
||||
Ok(Client {
|
||||
inner: Arc::new(ClientRef {
|
||||
accepts: config.accepts,
|
||||
#[cfg(feature = "cookies")]
|
||||
cookie_store: config.cookie_store.map(RwLock::new),
|
||||
gzip: config.gzip,
|
||||
brotli: config.brotli,
|
||||
hyper: hyper_client,
|
||||
headers: config.headers,
|
||||
redirect_policy: config.redirect_policy,
|
||||
@@ -448,7 +446,7 @@ impl ClientBuilder {
|
||||
/// This requires the optional `gzip` feature to be enabled
|
||||
#[cfg(feature = "gzip")]
|
||||
pub fn gzip(mut self, enable: bool) -> ClientBuilder {
|
||||
self.config.gzip = enable;
|
||||
self.config.accepts.gzip = enable;
|
||||
self
|
||||
}
|
||||
|
||||
@@ -470,7 +468,7 @@ impl ClientBuilder {
|
||||
/// This requires the optional `brotli` feature to be enabled
|
||||
#[cfg(feature = "brotli")]
|
||||
pub fn brotli(mut self, enable: bool) -> ClientBuilder {
|
||||
self.config.brotli = enable;
|
||||
self.config.accepts.brotli = enable;
|
||||
self
|
||||
}
|
||||
|
||||
@@ -976,12 +974,7 @@ impl Client {
|
||||
}
|
||||
}
|
||||
|
||||
let accept_encoding = match (self.inner.gzip, self.inner.brotli) {
|
||||
(true, true) => Some("gzip, br"),
|
||||
(true, false) => Some("gzip"),
|
||||
(false, true) => Some("br"),
|
||||
_ => None,
|
||||
};
|
||||
let accept_encoding = self.inner.accepts.as_str();
|
||||
|
||||
if accept_encoding.is_some()
|
||||
&& !headers.contains_key(ACCEPT_ENCODING)
|
||||
@@ -1092,8 +1085,7 @@ impl Config {
|
||||
}
|
||||
}
|
||||
|
||||
f.field("gzip", &self.gzip);
|
||||
f.field("brotli", &self.brotli);
|
||||
f.field("accepts", &self.accepts);
|
||||
|
||||
if !self.proxies.is_empty() {
|
||||
f.field("proxies", &self.proxies);
|
||||
@@ -1155,10 +1147,9 @@ impl Config {
|
||||
}
|
||||
|
||||
struct ClientRef {
|
||||
accepts: Accepts,
|
||||
#[cfg(feature = "cookies")]
|
||||
cookie_store: Option<RwLock<cookie::CookieStore>>,
|
||||
gzip: bool,
|
||||
brotli: bool,
|
||||
headers: HeaderMap,
|
||||
hyper: HyperClient,
|
||||
redirect_policy: redirect::Policy,
|
||||
@@ -1180,8 +1171,7 @@ impl ClientRef {
|
||||
}
|
||||
}
|
||||
|
||||
f.field("gzip", &self.gzip);
|
||||
f.field("brotli", &self.brotli);
|
||||
f.field("accepts", &self.accepts);
|
||||
|
||||
if !self.proxies.is_empty() {
|
||||
f.field("proxies", &self.proxies);
|
||||
@@ -1417,8 +1407,7 @@ impl Future for PendingRequest {
|
||||
let res = Response::new(
|
||||
res,
|
||||
self.url.clone(),
|
||||
self.client.gzip,
|
||||
self.client.brotli,
|
||||
self.client.accepts,
|
||||
self.timeout.take(),
|
||||
);
|
||||
return Poll::Ready(Ok(res));
|
||||
|
||||
@@ -18,6 +18,14 @@ use hyper::body::HttpBody;
|
||||
use super::super::Body;
|
||||
use crate::error;
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub(super) struct Accepts {
|
||||
#[cfg(feature = "gzip")]
|
||||
pub(super) gzip: bool,
|
||||
#[cfg(feature = "brotli")]
|
||||
pub(super) brotli: bool,
|
||||
}
|
||||
|
||||
/// A response decompressor over a non-blocking stream of chunks.
|
||||
///
|
||||
/// The inner decoder may be constructed asynchronously.
|
||||
@@ -25,13 +33,6 @@ pub(crate) struct Decoder {
|
||||
inner: Inner,
|
||||
}
|
||||
|
||||
enum DecoderType {
|
||||
#[cfg(feature = "gzip")]
|
||||
Gzip,
|
||||
#[cfg(feature = "brotli")]
|
||||
Brotli,
|
||||
}
|
||||
|
||||
enum Inner {
|
||||
/// A `PlainText` decoder just returns the response content as is.
|
||||
PlainText(super::body::ImplStream),
|
||||
@@ -54,6 +55,13 @@ struct Pending(Peekable<IoStream>, DecoderType);
|
||||
|
||||
struct IoStream(super::body::ImplStream);
|
||||
|
||||
enum DecoderType {
|
||||
#[cfg(feature = "gzip")]
|
||||
Gzip,
|
||||
#[cfg(feature = "brotli")]
|
||||
Brotli,
|
||||
}
|
||||
|
||||
impl fmt::Debug for Decoder {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_struct("Decoder").finish()
|
||||
@@ -177,26 +185,21 @@ impl Decoder {
|
||||
/// how to decode the content body of the request.
|
||||
///
|
||||
/// Uses the correct variant by inspecting the Content-Encoding header.
|
||||
pub(crate) fn detect(
|
||||
pub(super) fn detect(
|
||||
_headers: &mut HeaderMap,
|
||||
body: Body,
|
||||
check_gzip: bool,
|
||||
check_brotli: bool,
|
||||
_accepts: Accepts,
|
||||
) -> Decoder {
|
||||
if !check_gzip && !check_brotli {
|
||||
return Decoder::plain_text(body);
|
||||
}
|
||||
|
||||
#[cfg(feature = "gzip")]
|
||||
{
|
||||
if Decoder::detect_gzip(_headers) {
|
||||
if _accepts.gzip && Decoder::detect_gzip(_headers) {
|
||||
return Decoder::gzip(body);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "brotli")]
|
||||
{
|
||||
if Decoder::detect_brotli(_headers) {
|
||||
if _accepts.brotli && Decoder::detect_brotli(_headers) {
|
||||
return Decoder::brotli(body);
|
||||
}
|
||||
}
|
||||
@@ -317,3 +320,60 @@ impl Stream for IoStream {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ===== impl Accepts =====
|
||||
|
||||
impl Accepts {
|
||||
pub(super) fn none() -> Self {
|
||||
Accepts {
|
||||
#[cfg(feature = "gzip")]
|
||||
gzip: false,
|
||||
#[cfg(feature = "brotli")]
|
||||
brotli: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn as_str(&self) -> Option<&'static str> {
|
||||
match (self.is_gzip(), self.is_brotli()) {
|
||||
(true, true) => Some("gzip, br"),
|
||||
(true, false) => Some("gzip"),
|
||||
(false, true) => Some("br"),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_gzip(&self) -> bool {
|
||||
#[cfg(feature = "gzip")]
|
||||
{
|
||||
self.gzip
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "gzip"))]
|
||||
{
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn is_brotli(&self) -> bool {
|
||||
#[cfg(feature = "brotli")]
|
||||
{
|
||||
self.brotli
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "brotli"))]
|
||||
{
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Accepts {
|
||||
fn default() -> Accepts {
|
||||
Accepts {
|
||||
#[cfg(feature = "gzip")]
|
||||
gzip: true,
|
||||
#[cfg(feature = "brotli")]
|
||||
brotli: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
pub use self::body::Body;
|
||||
pub use self::client::{Client, ClientBuilder};
|
||||
pub(crate) use self::decoder::Decoder;
|
||||
pub use self::request::{Request, RequestBuilder};
|
||||
pub use self::response::{Response, ResponseBuilderExt};
|
||||
|
||||
#[cfg(feature = "blocking")]
|
||||
pub(crate) use self::decoder::Decoder;
|
||||
|
||||
pub mod body;
|
||||
pub mod client;
|
||||
pub mod decoder;
|
||||
|
||||
@@ -17,7 +17,7 @@ use tokio::time::Delay;
|
||||
use url::Url;
|
||||
|
||||
use super::body::Body;
|
||||
use super::Decoder;
|
||||
use super::decoder::{Accepts, Decoder};
|
||||
#[cfg(feature = "cookies")]
|
||||
use crate::cookie;
|
||||
|
||||
@@ -37,8 +37,7 @@ impl Response {
|
||||
pub(super) fn new(
|
||||
res: hyper::Response<hyper::Body>,
|
||||
url: Url,
|
||||
gzip: bool,
|
||||
brotli: bool,
|
||||
accepts: Accepts,
|
||||
timeout: Option<Delay>,
|
||||
) -> Response {
|
||||
let (parts, body) = res.into_parts();
|
||||
@@ -47,7 +46,7 @@ impl Response {
|
||||
let extensions = parts.extensions;
|
||||
|
||||
let mut headers = parts.headers;
|
||||
let decoder = Decoder::detect(&mut headers, Body::response(body, timeout), gzip, brotli);
|
||||
let decoder = Decoder::detect(&mut headers, Body::response(body, timeout), accepts);
|
||||
|
||||
Response {
|
||||
status,
|
||||
@@ -400,7 +399,7 @@ impl<T: Into<Body>> From<http::Response<T>> for Response {
|
||||
fn from(r: http::Response<T>) -> Response {
|
||||
let (mut parts, body) = r.into_parts();
|
||||
let body = body.into();
|
||||
let body = Decoder::detect(&mut parts.headers, body, false, false);
|
||||
let body = Decoder::detect(&mut parts.headers, body, Accepts::none());
|
||||
let url = parts
|
||||
.extensions
|
||||
.remove::<ResponseUrl>()
|
||||
|
||||
Reference in New Issue
Block a user