Add req field to Unit and remove cloned parts from request (#158)

Instead of cloning most of `Request`'s fields individually when
creating a `Unit`, this PR switches to just cloning `Request` and
stuffing it in `Unit`, and changes references to `unit.[field]` to
`unit.req.[field]` where appropriate.

Fixes #155
This commit is contained in:
Daniel Rivas
2020-09-26 18:22:10 +01:00
committed by GitHub
parent be9e3ca936
commit 8bba07a9af
4 changed files with 31 additions and 53 deletions

View File

@@ -1,5 +1,4 @@
use std::io::{Result as IoResult, Write};
use std::sync::{Arc, Mutex};
use std::time;
use qstring::QString;
@@ -12,15 +11,8 @@ use crate::agent::AgentState;
use crate::body::{self, Payload, SizedReader};
use crate::header;
use crate::stream::{self, connect_test, Stream};
use crate::Proxy;
use crate::{Error, Header, Request, Response};
#[cfg(feature = "tls")]
use crate::request::TLSClientConfig;
#[cfg(all(feature = "native-tls", not(feature = "tls")))]
use crate::request::TLSConnector;
#[cfg(feature = "cookie")]
use crate::pool::DEFAULT_HOST;
@@ -28,21 +20,12 @@ use crate::pool::DEFAULT_HOST;
///
/// *Internal API*
pub(crate) struct Unit {
pub agent: Arc<Mutex<AgentState>>,
pub req: Request,
pub url: Url,
pub is_chunked: bool,
pub query_string: String,
pub headers: Vec<Header>,
pub timeout_connect: u64,
pub timeout_read: u64,
pub timeout_write: u64,
pub deadline: Option<time::Instant>,
pub method: String,
pub proxy: Option<Proxy>,
#[cfg(feature = "tls")]
pub tls_config: Option<TLSClientConfig>,
#[cfg(all(feature = "native-tls", not(feature = "tls")))]
pub tls_connector: Option<TLSConnector>,
}
impl Unit {
@@ -99,26 +82,17 @@ impl Unit {
};
Unit {
agent: Arc::clone(&req.agent),
req: req.clone(),
url: url.clone(),
is_chunked,
query_string,
headers,
timeout_connect: req.timeout_connect,
timeout_read: req.timeout_read,
timeout_write: req.timeout_write,
deadline,
method: req.method.clone(),
proxy: req.proxy.clone(),
#[cfg(feature = "tls")]
tls_config: req.tls_config.clone(),
#[cfg(all(feature = "native-tls", not(feature = "tls")))]
tls_connector: req.tls_connector.clone(),
}
}
pub fn is_head(&self) -> bool {
self.method.eq_ignore_ascii_case("head")
self.req.method.eq_ignore_ascii_case("head")
}
#[cfg(test)]
@@ -217,8 +191,8 @@ pub(crate) fn connect(
let mut new_unit = Unit::new(req, &new_url, false, &empty);
// this is to follow how curl does it. POST, PUT etc change
// to GET on a redirect.
new_unit.method = match &unit.method[..] {
"GET" | "HEAD" => unit.method,
new_unit.req.method = match &unit.req.method[..] {
"GET" | "HEAD" => unit.req.method,
_ => "GET".into(),
};
return connect(req, new_unit, use_pooled, redirect_count + 1, empty, true);
@@ -305,11 +279,11 @@ fn connect_socket(unit: &Unit, use_pooled: bool) -> Result<(Stream, bool), Error
_ => return Err(Error::UnknownScheme(unit.url.scheme().to_string())),
};
if use_pooled {
let state = &mut unit.agent.lock().unwrap();
let state = &mut unit.req.agent.lock().unwrap();
// The connection may have been closed by the server
// due to idle timeout while it was sitting in the pool.
// Loop until we find one that is still good or run out of connections.
while let Some(stream) = state.pool.try_get_connection(&unit.url, &unit.proxy) {
while let Some(stream) = state.pool.try_get_connection(&unit.url, &unit.req.proxy) {
let server_closed = stream.server_closed()?;
if !server_closed {
return Ok((stream, true));
@@ -337,7 +311,7 @@ fn send_prelude(unit: &Unit, stream: &mut Stream, redir: bool) -> IoResult<()> {
write!(
prelude,
"{} {}{} HTTP/1.1\r\n",
unit.method,
unit.req.method,
unit.url.path(),
&unit.query_string
)?;
@@ -404,7 +378,7 @@ fn save_cookies(unit: &Unit, resp: &Response) {
}
// only lock if we know there is something to process
let state = &mut unit.agent.lock().unwrap();
let state = &mut unit.req.agent.lock().unwrap();
for raw_cookie in cookies.iter() {
let to_parse = if raw_cookie.to_lowercase().contains("domain=") {
(*raw_cookie).to_string()