Skip to content

src: update to hyper 0.12 #41

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 8, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ homepage = "https://github.com/ctz/hyper-rustls"
repository = "https://github.com/ctz/hyper-rustls"

[dependencies]
futures = "0.1.13"
hyper = "0.11"
ct-logs = "0.3"
futures = "0.1.21"
http = "0.1"
hyper = "0.12"
rustls = "0.12"
tokio-core = "0.1.7"
tokio-io = "0.1.1"
tokio-proto = "0.1"
tokio-rustls = { version = "0.5", features = [ "tokio-proto" ] }
tokio-service = "0.1.0"
tokio-rustls = "0.6"
tokio-tcp = "0.1"
webpki = "0.18.0-alpha"
webpki-roots = "0.14"
ct-logs = "0.3"
webpki-roots = "0.14"
32 changes: 16 additions & 16 deletions examples/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@ extern crate tokio_core;

use futures::{Future, Stream};
use hyper::{client, Uri};
use std::{env, io, fs};
use std::io::Write;
use std::str::FromStr;
use std::{env, fs, io};

fn main() {
// First parameter is target URL (mandatory)
Expand All @@ -32,30 +31,31 @@ fn main() {
None => None,
};

let mut core = tokio_core::reactor::Core::new().unwrap();
let handle = core.handle();
let https = match ca {
Some(ref mut rd) => {
let mut http = client::HttpConnector::new(4, &handle);
let mut http = client::HttpConnector::new(4);
http.enforce_http(false);
let mut tls = rustls::ClientConfig::new();
tls.root_store.add_pem_file(rd).unwrap();
hyper_rustls::HttpsConnector::from((http, tls))
}
None => hyper_rustls::HttpsConnector::new(4, &handle),
None => hyper_rustls::HttpsConnector::new(4),
};
let client = client::Client::configure().connector(https).build(&handle);
let client: client::Client<_, hyper::Body> = client::Client::builder().build(https);

let work = client.get(url).and_then(|res| {
println!("Status: {}", res.status());
println!("Headers:\n{}", res.headers());
res.body().for_each(|chunk| {
::std::io::stdout().write_all(&chunk).map(|_| ()).map_err(
From::from,
)
let fut = client
.get(url)
.inspect(|res| {
println!("Status:\n{}", res.status());
println!("Headers:\n{:#?}", res.headers());
})
});
if let Err(err) = core.run(work) {
.and_then(|res| res.into_body().concat2())
.inspect(|body| {
println!("Body:\n{}", String::from_utf8_lossy(&body));
});

let mut core = tokio_core::reactor::Core::new().unwrap();
if let Err(err) = core.run(fut) {
println!("FAILED: {}", err);
std::process::exit(1)
}
Expand Down
90 changes: 47 additions & 43 deletions examples/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,72 +3,76 @@
extern crate futures;
extern crate hyper;
extern crate rustls;
extern crate tokio_proto;
extern crate tokio_core;
extern crate tokio_rustls;
extern crate tokio_tcp;

use futures::future::FutureResult;
use hyper::header::ContentLength;
use hyper::server::{Http, Service, Request, Response};
use hyper::{Get, Post, StatusCode};
use tokio_rustls::proto;
use futures::future;
use futures::Stream;
use hyper::rt::Future;
use hyper::service::service_fn;
use hyper::{Body, Method, Request, Response, Server, StatusCode};
use rustls::internal::pemfile;
use std::{env, fs, io, sync};
use tokio_rustls::ServerConfigExt;

static INDEX: &'static [u8] = b"Try POST /echo\n";

#[derive(Clone, Copy)]
struct Echo;
type ResponseFuture = Box<Future<Item = Response<Body>, Error = hyper::Error> + Send>;

impl Service for Echo {
type Request = Request;
type Response = Response;
type Error = hyper::Error;
type Future = FutureResult<Response, hyper::Error>;

fn call(&self, req: Request) -> Self::Future {
futures::future::ok(match (req.method(), req.path()) {
(&Get, "/") | (&Get, "/echo") => {
Response::new()
.with_header(ContentLength(INDEX.len() as u64))
.with_body(INDEX)
}
(&Post, "/echo") => {
let mut res = Response::new();
if let Some(len) = req.headers().get::<ContentLength>() {
res.headers_mut().set(len.clone());
}
res.with_body(req.body())
}
_ => Response::new().with_status(StatusCode::NotFound),
})
}
fn echo(req: Request<Body>) -> ResponseFuture {
let mut response = Response::new(Body::empty());
match (req.method(), req.uri().path()) {
(&Method::GET, "/") => {
*response.body_mut() = Body::from(INDEX);
}
(&Method::POST, "/echo") => {
*response.body_mut() = req.into_body();
}
_ => {
*response.status_mut() = StatusCode::NOT_FOUND;
}
};
Box::new(future::ok(response))
}

fn load_certs(filename: &str) -> Vec<rustls::Certificate> {
let certfile = std::fs::File::open(filename).expect("cannot open certificate file");
let mut reader = std::io::BufReader::new(certfile);
let certfile = fs::File::open(filename).expect("cannot open certificate file");
let mut reader = io::BufReader::new(certfile);
pemfile::certs(&mut reader).unwrap()
}

fn load_private_key(filename: &str) -> rustls::PrivateKey {
let keyfile = std::fs::File::open(filename).expect("cannot open private key file");
let mut reader = std::io::BufReader::new(keyfile);
let keyfile = fs::File::open(filename).expect("cannot open private key file");
let mut reader = io::BufReader::new(keyfile);
let keys = pemfile::rsa_private_keys(&mut reader).unwrap();
assert!(keys.len() == 1);
keys[0].clone()
}

fn main() {
let port = match std::env::args().nth(1) {
let port = match env::args().nth(1) {
Some(ref p) => p.to_owned(),
None => "1337".to_owned(),
};
let addr = format!("127.0.0.1:{}", port).parse().unwrap();
let certs = load_certs("examples/sample.pem");
let key = load_private_key("examples/sample.rsa");
let mut cfg = rustls::ServerConfig::new(rustls::NoClientAuth::new());
cfg.set_single_cert(certs, key);
let tls = proto::Server::new(Http::new(), std::sync::Arc::new(cfg));
let tcp = tokio_proto::TcpServer::new(tls, addr);

let tls_cfg = {
let certs = load_certs("examples/sample.pem");
let key = load_private_key("examples/sample.rsa");
let mut cfg = rustls::ServerConfig::new(rustls::NoClientAuth::new());
cfg.set_single_cert(certs, key);
sync::Arc::new(cfg)
};

let tcp = tokio_tcp::TcpListener::bind(&addr).unwrap();
println!("Starting to serve on https://{}.", addr);
tcp.serve(|| Ok(Echo {}));
let tls = tcp.incoming().and_then(|s| tls_cfg.accept_async(s));
let fut = Server::builder(tls).serve(|| service_fn(echo));

let mut core = tokio_core::reactor::Core::new().unwrap();
if let Err(err) = core.run(fut) {
println!("FAILED: {}", err);
std::process::exit(1)
}
}
99 changes: 46 additions & 53 deletions src/connector.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,29 @@
use ct_logs;
use futures::{Future, Poll};
use hyper::client::connect::{self, Connect};
use hyper::client::HttpConnector;
use hyper::Uri;
use rustls::ClientConfig;
use std::{fmt, io};
use std::sync::Arc;
use stream::MaybeHttpsStream;
use tokio_core::reactor::Handle;
use std::{fmt, io};
use tokio_rustls::ClientConfigExt;
use tokio_service::Service;
use webpki::{DNSName, DNSNameRef};
use webpki::DNSNameRef;
use webpki_roots;
use ct_logs;

use stream::MaybeHttpsStream;

/// A Connector for the `https` scheme.
#[derive(Clone)]
pub struct HttpsConnector {
http: HttpConnector,
pub struct HttpsConnector<T> {
http: T,
tls_config: Arc<ClientConfig>,
}

impl HttpsConnector {
impl HttpsConnector<HttpConnector> {
/// Construct a new `HttpsConnector`.
///
/// Takes number of DNS worker threads.
pub fn new(threads: usize, handle: &Handle) -> HttpsConnector {
let mut http = HttpConnector::new(threads, handle);
pub fn new(threads: usize) -> Self {
let mut http = HttpConnector::new(threads);
http.enforce_http(false);
let mut config = ClientConfig::new();
config
Expand All @@ -38,77 +37,71 @@ impl HttpsConnector {
}
}

impl fmt::Debug for HttpsConnector {
impl<T> fmt::Debug for HttpsConnector<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("HttpsConnector").finish()
}
}

impl From<(HttpConnector, ClientConfig)> for HttpsConnector {
fn from(args: (HttpConnector, ClientConfig)) -> HttpsConnector {
impl<T> From<(T, ClientConfig)> for HttpsConnector<T> {
fn from(args: (T, ClientConfig)) -> Self {
HttpsConnector {
http: args.0,
tls_config: Arc::new(args.1),
}
}
}

impl Service for HttpsConnector {
type Request = Uri;
type Response = MaybeHttpsStream;
impl<T> Connect for HttpsConnector<T>
where
T: Connect<Error=io::Error>,
T::Transport: 'static,
T::Future: 'static,
{
type Transport = MaybeHttpsStream<T::Transport>;
type Error = io::Error;
type Future = HttpsConnecting;
type Future = HttpsConnecting<T::Transport>;

fn call(&self, uri: Uri) -> Self::Future {
let is_https = uri.scheme() == Some("https");
let host: DNSName = match uri.host() {
Some(host) => match DNSNameRef::try_from_ascii_str(host) {
Ok(host) => host.into(),
Err(err) => {
return HttpsConnecting(Box::new(::futures::future::err(io::Error::new(
io::ErrorKind::InvalidInput,
format!("invalid url: {:?}", err),
))))
}
},
None => {
return HttpsConnecting(Box::new(::futures::future::err(io::Error::new(
io::ErrorKind::InvalidInput,
"invalid url, missing host",
))))
}
};
let connecting = self.http.call(uri);
fn connect(&self, dst: connect::Destination) -> Self::Future {
let is_https = dst.scheme() == "https";

HttpsConnecting(if is_https {
let tls = self.tls_config.clone();
Box::new(
if !is_https {
let connecting = self.http.connect(dst);
let fut = Box::new(connecting.map(|(tcp, conn)| (MaybeHttpsStream::Http(tcp), conn)));
HttpsConnecting(fut)
} else {
let connecting = self.http.connect(dst.clone());
let cfg = self.tls_config.clone();
let fut = Box::new(
connecting
.and_then(move |tcp| {
tls.connect_async(host.as_ref(), tcp)
.and_then(move |(tcp, conn)| {
let dnsname = DNSNameRef::try_from_ascii_str(dst.host()).unwrap();
cfg.connect_async(dnsname, tcp)
.and_then(|tls| Ok((MaybeHttpsStream::Https(tls), conn)))
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))
})
.map(|tls| MaybeHttpsStream::Https(tls))
.map_err(|e| io::Error::new(io::ErrorKind::Other, e)),
)
} else {
Box::new(connecting.map(|tcp| MaybeHttpsStream::Http(tcp)))
})
);
HttpsConnecting(fut)
}
}
}

pub struct HttpsConnecting(Box<Future<Item = MaybeHttpsStream, Error = io::Error>>);
/// A Future representing work to connect to a URL, and a TLS handshake.
pub struct HttpsConnecting<T>(
Box<Future<Item = (MaybeHttpsStream<T>, connect::Connected), Error = io::Error> + Send>,
);

impl Future for HttpsConnecting {
type Item = MaybeHttpsStream;
impl<T> Future for HttpsConnecting<T> {
type Item = (MaybeHttpsStream<T>, connect::Connected);
type Error = io::Error;

fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
self.0.poll()
}
}

impl fmt::Debug for HttpsConnecting {
impl<T> fmt::Debug for HttpsConnecting<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.pad("HttpsConnecting")
}
Expand Down
12 changes: 6 additions & 6 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,30 +9,30 @@
//! extern crate hyper_rustls;
//! extern crate tokio_core;
//!
//! use hyper::{Client, Uri};
//! use hyper::{Body, Client, StatusCode, Uri};
//! use tokio_core::reactor;
//!
//! fn main() {
//! let mut core = reactor::Core::new().unwrap();
//! let url = ("https://hyper.rs").parse().unwrap();
//! let https = hyper_rustls::HttpsConnector::new(4);
//!
//! let client = hyper::Client::configure()
//! .connector(hyper_rustls::HttpsConnector::new(4, &core.handle()))
//! .build(&core.handle());
//! let client: Client<_, hyper::Body> = Client::builder().build(https);
//!
//! let res = core.run(client.get(url)).unwrap();
//! assert_eq!(res.status(), hyper::Ok);
//! assert_eq!(res.status(), StatusCode::OK);
//! }
//! ```

extern crate ct_logs;
extern crate futures;
extern crate http;
extern crate hyper;
extern crate rustls;
extern crate tokio_core;
extern crate tokio_io;
extern crate tokio_rustls;
extern crate tokio_service;
extern crate tokio_tcp;
extern crate webpki;
extern crate webpki_roots;

Expand Down
Loading