Remove Sync requirement of ReadWrite trait

3rd party TLS connections are currently required to provide a Sync
guarantee. Since ureq will only ever use the connection on a single
thread, this is not necessary.

The reason we end up with this bound is because we want Response and
Error to be Sync, in which case Rust's automatic inferral of Sync
fails.

This change "masks" the Stream in a wrapper making it Sync.

Close #474
This commit is contained in:
Martin Algesten
2022-01-30 13:53:47 +01:00
parent 219b5edf9e
commit 2c29cc230c
3 changed files with 9 additions and 7 deletions

View File

@@ -35,6 +35,7 @@ socks = { version = "0.3", optional = true }
serde = { version = "1", optional = true }
serde_json = { version = "1", optional = true }
encoding_rs = { version = "0.8", optional = true }
sync_wrapper = { version = "0.1" }
cookie_store = { version = "0.15", optional = true, default-features = false, features = ["preserve_order"] }
log = "0.4"
webpki = { version = "0.22", optional = true }

View File

@@ -3,6 +3,7 @@ use std::str::FromStr;
use std::{fmt, io::BufRead};
use chunked_transfer::Decoder as ChunkDecoder;
use sync_wrapper::SyncWrapper;
use url::Url;
use crate::error::{Error, ErrorKind::BadStatus};
@@ -67,7 +68,7 @@ pub struct Response {
// Boxed to avoid taking up too much size.
unit: Option<Box<Unit>>,
// Boxed to avoid taking up too much size.
stream: Box<Stream>,
stream: SyncWrapper<Box<Stream>>,
/// The redirect history of this response, if any. The history starts with
/// the first response received and ends with the response immediately
/// previous to this one.
@@ -292,7 +293,7 @@ impl Response {
self.length
};
let stream = self.stream;
let stream = self.stream.into_inner();
let unit = self.unit;
if let Some(unit) = &unit {
let result = stream.set_read_timeout(unit.agent.config.timeout_read);
@@ -512,7 +513,7 @@ impl Response {
status,
headers,
unit: unit.map(Box::new),
stream: Box::new(stream.into()),
stream: SyncWrapper::new(Box::new(stream.into())),
history: vec![],
length,
compression,
@@ -522,7 +523,7 @@ impl Response {
#[cfg(test)]
pub fn into_written_bytes(self) -> Vec<u8> {
// Deliberately consume `self` so that any access to `self.stream` must be non-shared.
self.stream.written_bytes()
self.stream.into_inner().written_bytes()
}
#[cfg(test)]

View File

@@ -18,7 +18,7 @@ use crate::error::ErrorKind;
use crate::unit::Unit;
/// Trait for things implementing [std::io::Read] + [std::io::Write]. Used in [TlsConnector].
pub trait ReadWrite: Read + Write + Send + Sync + 'static {
pub trait ReadWrite: Read + Write + Send + 'static {
fn socket(&self) -> Option<&TcpStream>;
}
@@ -31,7 +31,7 @@ pub trait TlsConnector: Send + Sync {
}
pub(crate) struct Stream {
inner: BufReader<Box<dyn Inner + Send + Sync + 'static>>,
inner: BufReader<Box<dyn Inner + Send + 'static>>,
}
trait Inner: Read + Write {
@@ -188,7 +188,7 @@ impl fmt::Debug for Stream {
}
impl Stream {
fn new(t: impl Inner + Send + Sync + 'static) -> Stream {
fn new(t: impl Inner + Send + 'static) -> Stream {
Stream::logged_create(Stream {
inner: BufReader::new(Box::new(t)),
})