Skip to content

Commit

Permalink
Crude compat layer while waiting on seanmonstar/reqwest#2039
Browse files Browse the repository at this point in the history
  • Loading branch information
novacrazy committed Jan 1, 2024
1 parent a733320 commit 7ba4b28
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 26 deletions.
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -68,17 +68,17 @@ lazy_static = { version = "1.4.0", optional = true }
url = { version = "2", optional = true }
thiserror = { version = "1", optional = true }
mime = { version = "0.3", optional = true }
headers = { version = "0.3", optional = true }
headers = { version = "0.4", optional = true }
reqwest = { version = "0.11.9", optional = true, default_features = false, features = ["gzip", "deflate"] }
http = { version = "0.2.6", optional = true }
http = { version = "1", optional = true }
serde_urlencoded = { version = "0.7.1", optional = true }
form_urlencoded = { version = "1.0.1", optional = true }
percent-encoding = { version = "2.1.0", optional = true }
arc-swap = { version = "1.5", optional = true }
base64 = { version = "0.21.0", optional = true }
tokio = { version = "1", optional = true, default_features = false, features = ["io-util"] }

tokio-tungstenite = { version = "0.20", optional = true, default_features = false, features = ["connect"] }
tokio-tungstenite = { version = "0.21", optional = true, default_features = false, features = ["connect"] }
miniz_oxide = { version = "0.7", optional = true }
futures = { version = "0.3", optional = true }
pin-project-lite = { version = "0.2.8", optional = true }
Expand Down
5 changes: 2 additions & 3 deletions src/client/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use std::sync::Arc;

use arc_swap::{ArcSwap, ArcSwapOption};
use headers::HeaderValue;

use crate::{
driver::{generic_client, Driver, DriverError, Encoding},
Expand All @@ -15,7 +14,7 @@ mod file;

struct ClientInner {
inner: reqwest::Client,
auth: ArcSwapOption<(AuthToken, HeaderValue)>,
auth: ArcSwapOption<(AuthToken, reqwest::header::HeaderValue)>,
uri: Arc<str>,
preferred_encoding: ArcSwap<Encoding>,
}
Expand Down Expand Up @@ -55,7 +54,7 @@ impl Client {
Some(token) => Some(Arc::new((
token,
match token.headervalue() {
Ok(header) => header,
Ok(header) => crate::driver::compat::new_headervalue_to_old(&header),
Err(e) => return Err(ClientError::DriverError(DriverError::from(e))),
},
))),
Expand Down
96 changes: 76 additions & 20 deletions src/driver/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,51 @@
pub(crate) mod compat {
use std::str::FromStr;

use headers::{HeaderMap as NewHeaderMap, HeaderName as NewHeaderName, HeaderValue as NewHeaderValue};
use http::{Method as NewMethod, StatusCode as NewStatus};
use reqwest::{
header::{HeaderMap as OldHeaderMap, HeaderName as OldHeaderName, HeaderValue as OldHeaderValue},
Method as OldMethod, StatusCode as OldStatus,
};

pub fn old_to_new_status(status: OldStatus) -> NewStatus {
unsafe { NewStatus::from_u16(status.as_u16()).unwrap_unchecked() }
}

pub fn add_new_headers_to_old(new: NewHeaderMap, old: &mut OldHeaderMap) {
for (k, v) in new.into_iter() {
if let Some(k) = k {
old.insert(OldHeaderName::from_str(k.as_str()).unwrap(), new_headervalue_to_old(&v));
}
}
}

pub fn new_headervalue_to_old(new: &NewHeaderValue) -> OldHeaderValue {
unsafe { OldHeaderValue::from_bytes(new.as_bytes()).unwrap_unchecked() }
}

pub fn new_to_old_method(new: NewMethod) -> OldMethod {
match new {
NewMethod::GET => OldMethod::GET,
NewMethod::POST => OldMethod::POST,
NewMethod::PUT => OldMethod::PUT,
NewMethod::DELETE => OldMethod::DELETE,
NewMethod::HEAD => OldMethod::HEAD,
NewMethod::OPTIONS => OldMethod::OPTIONS,
NewMethod::CONNECT => OldMethod::CONNECT,
NewMethod::PATCH => OldMethod::PATCH,
NewMethod::TRACE => OldMethod::TRACE,
_ => unreachable!(),
}
}
}

use std::sync::Arc;

use headers::{ContentType, HeaderMapExt, HeaderName, HeaderValue};
use http::Method;
use reqwest::{Request, Url};
use reqwest::{
header::{HeaderName, HeaderValue},
Method, Request, Url,
};

mod error;
pub use error::DriverError;
Expand Down Expand Up @@ -66,7 +109,7 @@ impl Driver {

pub fn set_token(&mut self, token: Option<AuthToken>) -> Result<(), DriverError> {
self.auth = match token {
Some(token) => Some(Arc::new((token, token.headervalue()?))),
Some(token) => Some(Arc::new((token, compat::new_headervalue_to_old(&token.headervalue()?)))),
None => None,
};

Expand Down Expand Up @@ -102,16 +145,22 @@ impl Driver {
// likely inlined, simple
cmd.format_path(&mut path)?;

let mut req = Request::new(CMD::HTTP_METHOD, Url::parse(&path)?);
let method = compat::new_to_old_method(CMD::HTTP_METHOD);

let mut req = Request::new(method.clone(), Url::parse(&path)?);

// likely inlined, often no-ops
cmd.add_headers(req.headers_mut());
{
let mut new_headers = headers::HeaderMap::new();
cmd.add_headers(&mut new_headers);
compat::add_new_headers_to_old(new_headers, req.headers_mut());
}

let body_size_hint = cmd.body_size_hint();

// if there is a body to serialize
if CMD::FLAGS.contains(CommandFlags::HAS_BODY) && body_size_hint > 0 {
match CMD::HTTP_METHOD {
match method {
// for methods without bodies, the "body" is treated as query parameters
Method::GET | Method::OPTIONS | Method::HEAD | Method::CONNECT | Method::TRACE => {
let url = req.url_mut();
Expand All @@ -130,18 +179,25 @@ impl Driver {
_ => {
let mut body = Vec::with_capacity(body_size_hint.max(128));

// TODO: Fix when reqwest updates
match self.encoding {
Encoding::JSON => {
serde_json::to_writer(&mut body, cmd.body())?;

req.headers_mut().typed_insert(ContentType::json());
req.headers_mut().insert(
HeaderName::from_static("content-type"),
HeaderValue::from_static("application/json"),
);
}

#[cfg(feature = "cbor")]
Encoding::CBOR => {
ciborium::ser::into_writer(cmd.body(), &mut body)?;

req.headers_mut().typed_insert(APPLICATION_CBOR.clone());
req.headers_mut().insert(
HeaderName::from_static("content-type"),
HeaderValue::from_static("application/cbor"),
);
}
}

Expand All @@ -157,13 +213,13 @@ impl Driver {
let response = self.inner.execute(req).await?;

let status = response.status();
let ct = response.headers().typed_get::<ContentType>();
let ct = response.headers().get(HeaderName::from_static("content-type")).cloned();
let body = response.bytes().await?;

if !status.is_success() {
return Err(match deserialize_ct(&body, ct) {
Ok(api_error) => DriverError::ApiError(api_error),
Err(_) => DriverError::GenericDriverError(status),
Err(_) => DriverError::GenericDriverError(compat::old_to_new_status(status)),
});
}

Expand All @@ -177,21 +233,21 @@ impl Driver {
}
}

lazy_static::lazy_static! {
pub(crate) static ref APPLICATION_CBOR: ContentType = ContentType::from("application/cbor".parse::<mime::Mime>().unwrap());
}
// lazy_static::lazy_static! {
// pub(crate) static ref APPLICATION_CBOR: ContentType = ContentType::from("application/cbor".parse::<mime::Mime>().unwrap());
// }

#[allow(unused_variables)]
fn deserialize_ct<T>(body: &[u8], ct: Option<ContentType>) -> Result<T, DriverError>
fn deserialize_ct<T>(body: &[u8], ct: Option<HeaderValue>) -> Result<T, DriverError>
where
T: serde::de::DeserializeOwned,
{
#[allow(unused_mut)]
let mut kind = Encoding::JSON;

#[cfg(feature = "cbor")]
if let Some(ct) = ct {
#[cfg(feature = "cbor")]
if ct == *APPLICATION_CBOR {
if ct.as_bytes() == b"application/cbor" {
kind = Encoding::CBOR;
}
}
Expand Down Expand Up @@ -238,16 +294,16 @@ impl Driver {

if status.is_success() {
if let Some(offset) = response.headers().get(HeaderName::from_static("upload-offset")) {
return Ok(offset.to_str()?.parse()?);
return Ok(offset.to_str().expect("Fix this").parse()?);
}
}

let ct = response.headers().typed_get::<ContentType>();
let ct = response.headers().get(HeaderName::from_static("content-type")).cloned();
let body = response.bytes().await?;

Err(match deserialize_ct(&body, ct) {
Ok(api_error) => DriverError::ApiError(api_error),
Err(_) => DriverError::GenericDriverError(status),
Err(_) => DriverError::GenericDriverError(compat::old_to_new_status(status)),
})
}
}

0 comments on commit 7ba4b28

Please sign in to comment.