fix redirect query parameters/hostname
This commit is contained in:
@@ -40,7 +40,7 @@ impl ::std::fmt::Debug for Request {
|
|||||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::result::Result<(), ::std::fmt::Error> {
|
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::result::Result<(), ::std::fmt::Error> {
|
||||||
let (path, query) = self.to_url()
|
let (path, query) = self.to_url()
|
||||||
.map(|u| {
|
.map(|u| {
|
||||||
let query = combine_query(&u, &self.query);
|
let query = combine_query(&u, &self.query, true);
|
||||||
(u.path().to_string(), query)
|
(u.path().to_string(), query)
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|_| ("BAD_URL".to_string(), "BAD_URL".to_string()));
|
.unwrap_or_else(|_| ("BAD_URL".to_string(), "BAD_URL".to_string()));
|
||||||
@@ -99,8 +99,8 @@ impl Request {
|
|||||||
self.to_url()
|
self.to_url()
|
||||||
.and_then(|url| {
|
.and_then(|url| {
|
||||||
let reader = payload.into_read();
|
let reader = payload.into_read();
|
||||||
let unit = Unit::new(&self, &url, &reader);
|
let unit = Unit::new(&self, &url, true, &reader);
|
||||||
connect(unit, &self.method, true, self.redirects, reader)
|
connect(&self, unit, &self.method, true, self.redirects, reader)
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|e| e.into())
|
.unwrap_or_else(|e| e.into())
|
||||||
}
|
}
|
||||||
@@ -455,7 +455,7 @@ impl Request {
|
|||||||
/// ```
|
/// ```
|
||||||
pub fn get_query(&self) -> Result<String, Error> {
|
pub fn get_query(&self) -> Result<String, Error> {
|
||||||
self.to_url()
|
self.to_url()
|
||||||
.map(|u| combine_query(&u, &self.query))
|
.map(|u| combine_query(&u, &self.query, true))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The normalized path of this request.
|
/// The normalized path of this request.
|
||||||
|
|||||||
20
src/unit.rs
20
src/unit.rs
@@ -27,7 +27,7 @@ pub struct Unit {
|
|||||||
impl Unit {
|
impl Unit {
|
||||||
//
|
//
|
||||||
|
|
||||||
fn new(req: &Request, url: &Url, body: &SizedReader) -> Self {
|
fn new(req: &Request, url: &Url, mix_queries: bool, body: &SizedReader) -> Self {
|
||||||
//
|
//
|
||||||
|
|
||||||
let is_chunked = req.header("transfer-encoding")
|
let is_chunked = req.header("transfer-encoding")
|
||||||
@@ -42,7 +42,7 @@ impl Unit {
|
|||||||
|
|
||||||
let hostname = url.host_str().unwrap_or(DEFAULT_HOST).to_string();
|
let hostname = url.host_str().unwrap_or(DEFAULT_HOST).to_string();
|
||||||
|
|
||||||
let query_string = combine_query(&url, &req.query);
|
let query_string = combine_query(&url, &req.query, mix_queries);
|
||||||
|
|
||||||
let cookie_headers: Vec<_> = {
|
let cookie_headers: Vec<_> = {
|
||||||
let mut state = req.agent.lock().unwrap();
|
let mut state = req.agent.lock().unwrap();
|
||||||
@@ -109,7 +109,8 @@ impl Unit {
|
|||||||
|
|
||||||
/// Perform a connection. Used recursively for redirects.
|
/// Perform a connection. Used recursively for redirects.
|
||||||
pub fn connect(
|
pub fn connect(
|
||||||
mut unit: Unit,
|
req: &Request,
|
||||||
|
unit: Unit,
|
||||||
method: &str,
|
method: &str,
|
||||||
use_pooled: bool,
|
use_pooled: bool,
|
||||||
redirects: u32,
|
redirects: u32,
|
||||||
@@ -126,7 +127,7 @@ pub fn connect(
|
|||||||
if is_recycled {
|
if is_recycled {
|
||||||
// we try open a new connection, this time there will be
|
// we try open a new connection, this time there will be
|
||||||
// no connection in the pool. don't use it.
|
// no connection in the pool. don't use it.
|
||||||
return connect(unit, method, false, redirects, body);
|
return connect(req, unit, method, false, redirects, body);
|
||||||
} else {
|
} else {
|
||||||
// not a pooled connection, propagate the error.
|
// not a pooled connection, propagate the error.
|
||||||
return Err(send_result.unwrap_err().into());
|
return Err(send_result.unwrap_err().into());
|
||||||
@@ -157,14 +158,13 @@ pub fn connect(
|
|||||||
.join(location)
|
.join(location)
|
||||||
.map_err(|_| Error::BadUrl(format!("Bad redirection: {}", location)))?;
|
.map_err(|_| Error::BadUrl(format!("Bad redirection: {}", location)))?;
|
||||||
|
|
||||||
// change this for every redirect since it is used when connection pooling.
|
|
||||||
unit.url = new_url;
|
|
||||||
|
|
||||||
// perform the redirect differently depending on 3xx code.
|
// perform the redirect differently depending on 3xx code.
|
||||||
match resp.status() {
|
match resp.status() {
|
||||||
301 | 302 | 303 => {
|
301 | 302 | 303 => {
|
||||||
let empty = Payload::Empty.into_read();
|
let empty = Payload::Empty.into_read();
|
||||||
return connect(unit, "GET", use_pooled, redirects - 1, empty);
|
// recreate the unit to get a new hostname and cookies for the new host.
|
||||||
|
let new_unit = Unit::new(req, &new_url, false, &empty);
|
||||||
|
return connect(req, new_unit, "GET", use_pooled, redirects - 1, empty);
|
||||||
}
|
}
|
||||||
, _ => (),
|
, _ => (),
|
||||||
// reinstate this with expect-100
|
// reinstate this with expect-100
|
||||||
@@ -211,8 +211,8 @@ fn match_cookies<'a>(jar: &'a CookieJar, domain: &str, path: &str, is_secure: bo
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Combine the query of the url and the query options set on the request object.
|
/// Combine the query of the url and the query options set on the request object.
|
||||||
fn combine_query(url: &Url, query: &QString) -> String {
|
fn combine_query(url: &Url, query: &QString, mix_queries: bool) -> String {
|
||||||
match (url.query(), query.len() > 0) {
|
match (url.query(), query.len() > 0 && mix_queries) {
|
||||||
(Some(urlq), true) => format!("?{}&{}", urlq, query),
|
(Some(urlq), true) => format!("?{}&{}", urlq, query),
|
||||||
(Some(urlq), false) => format!("?{}", urlq),
|
(Some(urlq), false) => format!("?{}", urlq),
|
||||||
(None, true) => format!("?{}", query),
|
(None, true) => format!("?{}", query),
|
||||||
|
|||||||
Reference in New Issue
Block a user