mirror of https://github.com/fafhrd91/actix-web
respect max_redirects configuration
This commit is contained in:
parent
d10f776837
commit
05527b3e51
|
@ -191,6 +191,7 @@ impl ClientBuilder {
|
||||||
let config = ClientConfig {
|
let config = ClientConfig {
|
||||||
headers: self.headers,
|
headers: self.headers,
|
||||||
timeout: self.timeout,
|
timeout: self.timeout,
|
||||||
|
max_redirects: self.max_redirects,
|
||||||
connector,
|
connector,
|
||||||
};
|
};
|
||||||
Client(Rc::new(config))
|
Client(Rc::new(config))
|
||||||
|
|
|
@ -5,6 +5,7 @@ use std::pin::Pin;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::task::{Context, Poll};
|
use std::task::{Context, Poll};
|
||||||
use std::{fmt, io, mem, net};
|
use std::{fmt, io, mem, net};
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
use actix_codec::{AsyncRead, AsyncWrite, Framed};
|
use actix_codec::{AsyncRead, AsyncWrite, Framed};
|
||||||
use actix_http::body::Body;
|
use actix_http::body::Body;
|
||||||
|
@ -12,7 +13,7 @@ use actix_http::client::{
|
||||||
Connect as ClientConnect, ConnectError, Connection, SendRequestError,
|
Connect as ClientConnect, ConnectError, Connection, SendRequestError,
|
||||||
};
|
};
|
||||||
use actix_http::h1::ClientCodec;
|
use actix_http::h1::ClientCodec;
|
||||||
use actix_http::http::{HeaderMap, Uri};
|
use actix_http::http::HeaderMap;
|
||||||
use actix_http::Extensions;
|
use actix_http::Extensions;
|
||||||
use actix_http::{RequestHead, RequestHeadType, ResponseHead};
|
use actix_http::{RequestHead, RequestHeadType, ResponseHead};
|
||||||
use actix_service::Service;
|
use actix_service::Service;
|
||||||
|
@ -27,6 +28,7 @@ pub(crate) trait Connect {
|
||||||
head: RequestHead,
|
head: RequestHead,
|
||||||
body: Body,
|
body: Body,
|
||||||
addr: Option<net::SocketAddr>,
|
addr: Option<net::SocketAddr>,
|
||||||
|
max_redirect: usize,
|
||||||
) -> Pin<Box<dyn Future<Output = Result<ClientResponse, SendRequestError>>>>;
|
) -> Pin<Box<dyn Future<Output = Result<ClientResponse, SendRequestError>>>>;
|
||||||
|
|
||||||
fn send_request_extra(
|
fn send_request_extra(
|
||||||
|
@ -85,12 +87,15 @@ where
|
||||||
head: RequestHead,
|
head: RequestHead,
|
||||||
body: Body,
|
body: Body,
|
||||||
addr: Option<net::SocketAddr>,
|
addr: Option<net::SocketAddr>,
|
||||||
|
max_redirects: usize,
|
||||||
) -> Pin<Box<dyn Future<Output = Result<ClientResponse, SendRequestError>>>> {
|
) -> Pin<Box<dyn Future<Output = Result<ClientResponse, SendRequestError>>>> {
|
||||||
fn deal_with_redirects<S>(
|
fn deal_with_redirects<S>(
|
||||||
backend: Rc<RefCell<S>>,
|
backend: Rc<RefCell<S>>,
|
||||||
head: RequestHead,
|
head: RequestHead,
|
||||||
body: Body,
|
body: Body,
|
||||||
addr: Option<net::SocketAddr>,
|
addr: Option<net::SocketAddr>,
|
||||||
|
max_redirects: usize,
|
||||||
|
redirect_count: usize,
|
||||||
) -> Pin<Box<dyn Future<Output = Result<ClientResponse, SendRequestError>>>>
|
) -> Pin<Box<dyn Future<Output = Result<ClientResponse, SendRequestError>>>>
|
||||||
where
|
where
|
||||||
S: Service<Request = ClientConnect, Error = ConnectError> + 'static,
|
S: Service<Request = ClientConnect, Error = ConnectError> + 'static,
|
||||||
|
@ -139,23 +144,25 @@ where
|
||||||
if resphead.status.is_redirection();
|
if resphead.status.is_redirection();
|
||||||
if let Some(location_value) = resphead.headers.get(actix_http::http::header::LOCATION);
|
if let Some(location_value) = resphead.headers.get(actix_http::http::header::LOCATION);
|
||||||
if let Ok(location_str) = location_value.to_str();
|
if let Ok(location_str) = location_value.to_str();
|
||||||
if let Ok(location_uri) = location_str.parse::<Uri>();
|
|
||||||
then {
|
then {
|
||||||
|
if redirect_count >= max_redirects {
|
||||||
|
// TODO: need a better error
|
||||||
|
return Err(SendRequestError::Timeout);
|
||||||
|
}
|
||||||
if resphead.status == actix_http::http::StatusCode::SEE_OTHER {
|
if resphead.status == actix_http::http::StatusCode::SEE_OTHER {
|
||||||
reqhead.method = actix_http::http::Method::GET;
|
reqhead.method = actix_http::http::Method::GET;
|
||||||
reqbody = Body::None;
|
reqbody = Body::None;
|
||||||
}
|
}
|
||||||
let mut parts = location_uri.clone().into_parts();
|
let base_url = Url::parse(&uri.to_string()).unwrap();
|
||||||
if location_uri.authority().is_none() {
|
let url_parser = Url::options().base_url(Some(&base_url));
|
||||||
parts.scheme = Some(uri.scheme().unwrap().clone());
|
reqhead.uri = url_parser.parse(location_str).unwrap().as_str().parse().unwrap();
|
||||||
parts.authority = Some(uri.authority().unwrap().clone());
|
|
||||||
}
|
|
||||||
reqhead.uri = Uri::from_parts(parts).unwrap();
|
|
||||||
return deal_with_redirects(
|
return deal_with_redirects(
|
||||||
backend.clone(),
|
backend.clone(),
|
||||||
reqhead,
|
reqhead,
|
||||||
reqbody,
|
reqbody,
|
||||||
addr,
|
addr,
|
||||||
|
max_redirects,
|
||||||
|
redirect_count + 1,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
@ -167,7 +174,7 @@ where
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
deal_with_redirects(self.0.clone(), head, body, addr)
|
deal_with_redirects(self.0.clone(), head, body, addr, max_redirects, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send_request_extra(
|
fn send_request_extra(
|
||||||
|
|
|
@ -148,6 +148,7 @@ pub(crate) struct ClientConfig {
|
||||||
pub(crate) connector: RefCell<Box<dyn Connect>>,
|
pub(crate) connector: RefCell<Box<dyn Connect>>,
|
||||||
pub(crate) headers: HeaderMap,
|
pub(crate) headers: HeaderMap,
|
||||||
pub(crate) timeout: Option<Duration>,
|
pub(crate) timeout: Option<Duration>,
|
||||||
|
pub(crate) max_redirects: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Client {
|
impl Default for Client {
|
||||||
|
@ -158,6 +159,7 @@ impl Default for Client {
|
||||||
))))),
|
))))),
|
||||||
headers: HeaderMap::new(),
|
headers: HeaderMap::new(),
|
||||||
timeout: Some(Duration::from_secs(5)),
|
timeout: Some(Duration::from_secs(5)),
|
||||||
|
max_redirects: 10,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -186,7 +186,7 @@ impl RequestSender {
|
||||||
|
|
||||||
let fut = match self {
|
let fut = match self {
|
||||||
RequestSender::Owned(head) => {
|
RequestSender::Owned(head) => {
|
||||||
connector.send_request(head, body.into(), addr)
|
connector.send_request(head, body.into(), addr, config.max_redirects)
|
||||||
}
|
}
|
||||||
RequestSender::Rc(head, extra_headers) => {
|
RequestSender::Rc(head, extra_headers) => {
|
||||||
connector.send_request_extra(head, extra_headers, body.into(), addr)
|
connector.send_request_extra(head, extra_headers, body.into(), addr)
|
||||||
|
|
Loading…
Reference in New Issue