mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
Abstracts the hyper connection to a servo HttpRequester trait
servo/servo#6727
This commit is contained in:
parent
67aa11323b
commit
6cba33a50b
2 changed files with 82 additions and 192 deletions
|
@ -21,6 +21,10 @@ use hyper::Error as HttpError;
|
|||
use hyper::client::Request;
|
||||
use hyper::header::StrictTransportSecurity;
|
||||
use hyper::header::{AcceptEncoding, Accept, ContentLength, ContentType, Host, Location, qitem, Quality, QualityItem};
|
||||
use hyper::client::{Request, Response};
|
||||
use hyper::header::{AcceptEncoding, Accept, ContentLength, ContentType, Host, Location, qitem, StrictTransportSecurity};
|
||||
use hyper::header::{Quality, QualityItem};
|
||||
use hyper::Error as HttpError;
|
||||
use hyper::method::Method;
|
||||
use hyper::mime::{Mime, TopLevel, SubLevel};
|
||||
use hyper::net::{Fresh, HttpsConnector, Openssl, NetworkConnector, NetworkStream};
|
||||
|
@ -105,20 +109,9 @@ fn load_for_consumer(load_data: LoadData,
|
|||
devtools_chan: Option<Sender<DevtoolsControlMsg>>,
|
||||
hsts_list: Arc<Mutex<HSTSList>>) {
|
||||
|
||||
let connector = {
|
||||
// TODO: Is this still necessary? The type system is making it really hard to support both
|
||||
// connectors. SSL is working, so it's not clear to me if the original rationale still
|
||||
// stands?
|
||||
// if opts::get().nossl {
|
||||
// &HttpConnector
|
||||
let mut context = SslContext::new(SslMethod::Sslv23).unwrap();
|
||||
context.set_verify(SSL_VERIFY_PEER, None);
|
||||
context.set_CA_file(&resources_dir_path().join("certs")).unwrap();
|
||||
let requester = NetworkHttpRequester::new();
|
||||
|
||||
&HttpsConnector::new(Openssl { context: Arc::new(context) })
|
||||
};
|
||||
|
||||
match load(load_data, resource_mgr_chan, devtools_chan, hsts_list, connector) {
|
||||
match load(load_data, resource_mgr_chan, devtools_chan, hsts_list, &requester) {
|
||||
Err(LoadError::UnsupportedScheme(url)) => {
|
||||
let s = format!("{} request, but we don't support that scheme", &*url.scheme);
|
||||
send_error(url, s, start_chan)
|
||||
|
@ -150,40 +143,67 @@ fn load_for_consumer(load_data: LoadData,
|
|||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn connect<C, S>(url: Url,
|
||||
method: Method,
|
||||
connector: &C) -> Result<Request<Fresh>, LoadError> where
|
||||
C: NetworkConnector<Stream=S>,
|
||||
S: Into<Box<NetworkStream + Send>> {
|
||||
let connection = Request::with_connector(method, url.clone(), connector);
|
||||
struct NetworkHttpRequester {
|
||||
connector: HttpsConnector<Openssl>
|
||||
}
|
||||
|
||||
let ssl_err_string = "Some(OpenSslErrors([UnknownError { library: \"SSL routines\", \
|
||||
function: \"SSL3_GET_SERVER_CERTIFICATE\", \
|
||||
reason: \"certificate verify failed\" }]))";
|
||||
impl NetworkHttpRequester {
|
||||
fn new() -> NetworkHttpRequester {
|
||||
// TODO: Is this still necessary? The type system is making it really hard to support both
|
||||
// connectors. SSL is working, so it's not clear to me if the original rationale still
|
||||
// stands?
|
||||
// if opts::get().nossl {
|
||||
// &HttpConnector
|
||||
let mut context = SslContext::new(SslMethod::Sslv23).unwrap();
|
||||
context.set_verify(SSL_VERIFY_PEER, None);
|
||||
context.set_CA_file(&resources_dir_path().join("certs")).unwrap();
|
||||
|
||||
match connection {
|
||||
Ok(req) => Ok(req),
|
||||
|
||||
Err(HttpError::Io(ref io_error)) if (
|
||||
io_error.kind() == io::ErrorKind::Other &&
|
||||
io_error.description() == "Error in OpenSSL" &&
|
||||
// FIXME: This incredibly hacky. Make it more robust, and at least test it.
|
||||
format!("{:?}", io_error.cause()) == ssl_err_string
|
||||
) => {
|
||||
Err(
|
||||
LoadError::Ssl(
|
||||
url.clone(),
|
||||
format!("ssl error {:?}: {:?} {:?}", io_error.kind(), io_error.description(), io_error.cause())
|
||||
)
|
||||
)
|
||||
},
|
||||
Err(e) => {
|
||||
Err(LoadError::Connection(url, e.description().to_string()))
|
||||
NetworkHttpRequester {
|
||||
connector: HttpsConnector::new(Openssl { context: Arc::new(context) })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HttpRequester for NetworkHttpRequester {
|
||||
fn send(&self, request: Request<Fresh>) -> Result<Response, LoadError> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn build(&self, url: Url, method: Method) -> Result<Request<Fresh>, LoadError> {
|
||||
let connection = Request::with_connector(method, url.clone(), &self.connector);
|
||||
|
||||
let ssl_err_string = "Some(OpenSslErrors([UnknownError { library: \"SSL routines\", \
|
||||
function: \"SSL3_GET_SERVER_CERTIFICATE\", \
|
||||
reason: \"certificate verify failed\" }]))";
|
||||
|
||||
match connection {
|
||||
Ok(req) => Ok(req),
|
||||
|
||||
Err(HttpError::Io(ref io_error)) if (
|
||||
io_error.kind() == io::ErrorKind::Other &&
|
||||
io_error.description() == "Error in OpenSSL" &&
|
||||
// FIXME: This incredibly hacky. Make it more robust, and at least test it.
|
||||
format!("{:?}", io_error.cause()) == ssl_err_string
|
||||
) => {
|
||||
Err(
|
||||
LoadError::Ssl(
|
||||
url.clone(),
|
||||
format!("ssl error {:?}: {:?} {:?}", io_error.kind(), io_error.description(), io_error.cause())
|
||||
)
|
||||
)
|
||||
},
|
||||
Err(e) => {
|
||||
Err(LoadError::Connection(url, e.description().to_string()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait HttpRequester {
|
||||
fn build(&self, url: Url, method: Method) -> Result<Request<Fresh>, LoadError>;
|
||||
fn send(&self, request: Request<Fresh>) -> Result<Response, LoadError>;
|
||||
}
|
||||
|
||||
pub enum LoadError {
|
||||
UnsupportedScheme(Url),
|
||||
Connection(Url, String),
|
||||
|
@ -194,14 +214,12 @@ pub enum LoadError {
|
|||
MaxRedirects(Url)
|
||||
}
|
||||
|
||||
fn load<C, S>(mut load_data: LoadData,
|
||||
resource_mgr_chan: IpcSender<ControlMsg>,
|
||||
devtools_chan: Option<Sender<DevtoolsControlMsg>>,
|
||||
hsts_list: Arc<Mutex<HSTSList>>,
|
||||
connector: &C) -> Result<(Box<Read>, Metadata), LoadError> where
|
||||
C: NetworkConnector<Stream=S>,
|
||||
S: Into<Box<NetworkStream + Send>> {
|
||||
|
||||
pub fn load(mut load_data: LoadData,
|
||||
resource_mgr_chan: IpcSender<ControlMsg>,
|
||||
devtools_chan: Option<Sender<DevtoolsControlMsg>>,
|
||||
hsts_list: Arc<Mutex<HSTSList>>,
|
||||
requester: &HttpRequester)
|
||||
-> Result<(Box<Read>, Metadata), LoadError> {
|
||||
// FIXME: At the time of writing this FIXME, servo didn't have any central
|
||||
// location for configuration. If you're reading this and such a
|
||||
// repository DOES exist, please update this constant to use it.
|
||||
|
@ -243,7 +261,7 @@ fn load<C, S>(mut load_data: LoadData,
|
|||
|
||||
info!("requesting {}", url.serialize());
|
||||
|
||||
let mut req = try!(connect(url.clone(), load_data.method.clone(), connector));
|
||||
let mut req = try!(requester.build(url.clone(), load_data.method.clone()));
|
||||
|
||||
//Ensure that the host header is set from the original url
|
||||
let host = Host {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue