mirror of
https://github.com/servo/servo.git
synced 2025-08-04 21:20:23 +01:00
Abstracts out initial client connection and SSL errors (which I don't think are working?)
servo/servo#6727
This commit is contained in:
parent
c8c36f4490
commit
9ac250c62c
1 changed files with 60 additions and 39 deletions
|
@ -9,6 +9,8 @@ use net_traits::ProgressMsg::{Payload, Done};
|
||||||
use net_traits::hosts::replace_hosts;
|
use net_traits::hosts::replace_hosts;
|
||||||
use net_traits::{ControlMsg, CookieSource, LoadData, Metadata, LoadConsumer, IncludeSubdomains};
|
use net_traits::{ControlMsg, CookieSource, LoadData, Metadata, LoadConsumer, IncludeSubdomains};
|
||||||
use resource_task::{start_sending_opt, start_sending_sniffed_opt};
|
use resource_task::{start_sending_opt, start_sending_sniffed_opt};
|
||||||
|
use hsts::{HSTSList, secure_url};
|
||||||
|
use file_loader;
|
||||||
|
|
||||||
use file_loader;
|
use file_loader;
|
||||||
use ipc_channel::ipc::{self, IpcSender};
|
use ipc_channel::ipc::{self, IpcSender};
|
||||||
|
@ -21,7 +23,7 @@ use hyper::header::StrictTransportSecurity;
|
||||||
use hyper::header::{AcceptEncoding, Accept, ContentLength, ContentType, Host, Location, qitem, Quality, QualityItem};
|
use hyper::header::{AcceptEncoding, Accept, ContentLength, ContentType, Host, Location, qitem, Quality, QualityItem};
|
||||||
use hyper::method::Method;
|
use hyper::method::Method;
|
||||||
use hyper::mime::{Mime, TopLevel, SubLevel};
|
use hyper::mime::{Mime, TopLevel, SubLevel};
|
||||||
use hyper::net::{HttpStream, HttpConnector, HttpsConnector, Openssl, NetworkConnector, NetworkStream};
|
use hyper::net::{Fresh, HttpsConnector, Openssl, NetworkConnector, NetworkStream};
|
||||||
use hyper::status::{StatusCode, StatusClass};
|
use hyper::status::{StatusCode, StatusClass};
|
||||||
use ipc_channel::ipc::{self, IpcSender};
|
use ipc_channel::ipc::{self, IpcSender};
|
||||||
use log;
|
use log;
|
||||||
|
@ -32,6 +34,8 @@ use std::io::{self, Read, Write};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
use std::sync::mpsc::{Sender, channel};
|
use std::sync::mpsc::{Sender, channel};
|
||||||
|
use util::task::spawn_named;
|
||||||
|
use util::resource_files::resources_dir_path;
|
||||||
use url::{Url, UrlParser};
|
use url::{Url, UrlParser};
|
||||||
use util::opts;
|
use util::opts;
|
||||||
use util::resource_files::resources_dir_path;
|
use util::resource_files::resources_dir_path;
|
||||||
|
@ -104,7 +108,7 @@ fn load_for_consumer(load_data: LoadData,
|
||||||
let connector = {
|
let connector = {
|
||||||
// TODO: Is this still necessary? The type system is making it really hard to support both
|
// 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
|
// connectors. SSL is working, so it's not clear to me if the original rationale still
|
||||||
// stands
|
// stands?
|
||||||
// if opts::get().nossl {
|
// if opts::get().nossl {
|
||||||
// &HttpConnector
|
// &HttpConnector
|
||||||
let mut context = SslContext::new(SslMethod::Sslv23).unwrap();
|
let mut context = SslContext::new(SslMethod::Sslv23).unwrap();
|
||||||
|
@ -119,7 +123,7 @@ fn load_for_consumer(load_data: LoadData,
|
||||||
let s = format!("{} request, but we don't support that scheme", &*url.scheme);
|
let s = format!("{} request, but we don't support that scheme", &*url.scheme);
|
||||||
send_error(url, s, start_chan)
|
send_error(url, s, start_chan)
|
||||||
}
|
}
|
||||||
Err(LoadError::Client(url, e)) => {
|
Err(LoadError::Connection(url, e)) => {
|
||||||
send_error(url, e, start_chan)
|
send_error(url, e, start_chan)
|
||||||
}
|
}
|
||||||
Err(LoadError::MaxRedirects(url)) => {
|
Err(LoadError::MaxRedirects(url)) => {
|
||||||
|
@ -127,23 +131,66 @@ fn load_for_consumer(load_data: LoadData,
|
||||||
}
|
}
|
||||||
Err(LoadError::Cors(url, msg)) |
|
Err(LoadError::Cors(url, msg)) |
|
||||||
Err(LoadError::InvalidRedirect(url, msg)) |
|
Err(LoadError::InvalidRedirect(url, msg)) |
|
||||||
Err(LoadError::Decoding(url, msg)) |
|
Err(LoadError::Decoding(url, msg)) => {
|
||||||
Err(LoadError::InvalidFile(url, msg)) => {
|
|
||||||
send_error(url, msg, start_chan)
|
send_error(url, msg, start_chan)
|
||||||
}
|
}
|
||||||
|
Err(LoadError::Ssl(url, msg)) => {
|
||||||
|
info!("ssl validation error {}, '{}'", url.serialize(), msg);
|
||||||
|
|
||||||
|
let mut image = resources_dir_path();
|
||||||
|
image.push("badcert.html");
|
||||||
|
let load_data = LoadData::new(Url::from_file_path(&*image).unwrap(), None);
|
||||||
|
|
||||||
|
file_loader::factory(load_data, start_chan, classifier)
|
||||||
|
|
||||||
|
}
|
||||||
Ok((mut response_reader, metadata)) => {
|
Ok((mut response_reader, metadata)) => {
|
||||||
send_data(&mut response_reader, start_chan, metadata, classifier);
|
send_data(&mut response_reader, start_chan, metadata, classifier)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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);
|
||||||
|
|
||||||
|
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()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum LoadError {
|
enum LoadError {
|
||||||
UnsupportedScheme(Url),
|
UnsupportedScheme(Url),
|
||||||
Client(Url, String),
|
Connection(Url, String),
|
||||||
Cors(Url, String),
|
Cors(Url, String),
|
||||||
|
Ssl(Url, String),
|
||||||
InvalidRedirect(Url, String),
|
InvalidRedirect(Url, String),
|
||||||
Decoding(Url, String),
|
Decoding(Url, String),
|
||||||
InvalidFile(Url, String),
|
|
||||||
MaxRedirects(Url)
|
MaxRedirects(Url)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,33 +248,7 @@ fn load<C, S>(mut load_data: LoadData,
|
||||||
|
|
||||||
info!("requesting {}", url.serialize());
|
info!("requesting {}", url.serialize());
|
||||||
|
|
||||||
let ssl_err_string = "Some(OpenSslErrors([UnknownError { library: \"SSL routines\", \
|
let mut req = try!(connect(url.clone(), load_data.method.clone(), connector));
|
||||||
function: \"SSL3_GET_SERVER_CERTIFICATE\", \
|
|
||||||
reason: \"certificate verify failed\" }]))";
|
|
||||||
|
|
||||||
let req = Request::with_connector(load_data.method.clone(), url.clone(), connector);
|
|
||||||
|
|
||||||
let mut req = match req {
|
|
||||||
Ok(req) => 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
|
|
||||||
) => {
|
|
||||||
let mut image = resources_dir_path();
|
|
||||||
image.push("badcert.html");
|
|
||||||
let file_url = Url::from_file_path(&*image).unwrap();
|
|
||||||
|
|
||||||
match File::open(image.clone()) {
|
|
||||||
Ok(f) => return Ok((Box::new(f), Metadata::default(file_url))),
|
|
||||||
Err(_) => return Err(LoadError::InvalidFile(file_url, image.to_str().unwrap().to_string()))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Err(e) => {
|
|
||||||
return Err(LoadError::Client(url, e.description().to_string()));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//Ensure that the host header is set from the original url
|
//Ensure that the host header is set from the original url
|
||||||
let host = Host {
|
let host = Host {
|
||||||
|
@ -288,13 +309,13 @@ reason: \"certificate verify failed\" }]))";
|
||||||
let mut writer = match req.start() {
|
let mut writer = match req.start() {
|
||||||
Ok(w) => w,
|
Ok(w) => w,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return Err(LoadError::Client(url, e.description().to_string()));
|
return Err(LoadError::Connection(url, e.description().to_string()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
match writer.write_all(&*data) {
|
match writer.write_all(&*data) {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return Err(LoadError::Client(url, e.description().to_string()));
|
return Err(LoadError::Connection(url, e.description().to_string()));
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
|
@ -308,7 +329,7 @@ reason: \"certificate verify failed\" }]))";
|
||||||
match req.start() {
|
match req.start() {
|
||||||
Ok(w) => w,
|
Ok(w) => w,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return Err(LoadError::Client(url, e.description().to_string()));
|
return Err(LoadError::Connection(url, e.description().to_string()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -330,7 +351,7 @@ reason: \"certificate verify failed\" }]))";
|
||||||
let response = match writer.send() {
|
let response = match writer.send() {
|
||||||
Ok(r) => r,
|
Ok(r) => r,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return Err(LoadError::Client(url, e.description().to_string()));
|
return Err(LoadError::Connection(url, e.description().to_string()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue