From 4aefc9ba33beefb984a495faa3555cb10f90e252 Mon Sep 17 00:00:00 2001 From: Richard Whitehouse Date: Thu, 19 Mar 2020 21:05:16 +0000 Subject: [PATCH] [Rust Sever] Upgrade to openssl 0.10 (#5564) * [Rust Server] Upgrade to openssl 0.10 Use hyper-openssl/openssl instead of hyper-tls/native-tls/openssl on Linux * Update samples --- .../main/resources/rust-server/Cargo.mustache | 26 +++++--- .../rust-server/client-imports.mustache | 7 +- .../resources/rust-server/client-mod.mustache | 57 +++++++++++------ .../rust-server/example-client-main.mustache | 14 ++-- .../example-server-common.mustache | 63 +++++++++++------- .../rust-server/example-server-main.mustache | 30 ++------- .../main/resources/rust-server/lib.mustache | 12 ++-- .../rust-server/server-callbacks.mustache | 51 ++++++++++----- .../output/multipart-v3/Cargo.toml | 21 ++++-- .../multipart-v3/examples/client/main.rs | 4 +- .../multipart-v3/examples/server/main.rs | 30 ++------- .../multipart-v3/examples/server/server.rs | 63 +++++++++++------- .../output/multipart-v3/src/client/mod.rs | 64 ++++++++++++------- .../output/multipart-v3/src/lib.rs | 9 +-- .../rust-server/output/openapi-v3/Cargo.toml | 24 ++++--- .../output/openapi-v3/examples/client/main.rs | 14 ++-- .../openapi-v3/examples/client/server.rs | 63 +++++++++++------- .../output/openapi-v3/examples/server/main.rs | 30 ++------- .../openapi-v3/examples/server/server.rs | 63 +++++++++++------- .../output/openapi-v3/src/client/mod.rs | 64 ++++++++++++------- .../rust-server/output/openapi-v3/src/lib.rs | 7 +- .../output/openapi-v3/src/server/callbacks.rs | 58 +++++++++++------ .../rust-server/output/ops-v3/Cargo.toml | 21 ++++-- .../output/ops-v3/examples/client/main.rs | 4 +- .../output/ops-v3/examples/server/main.rs | 30 ++------- .../output/ops-v3/examples/server/server.rs | 63 +++++++++++------- .../output/ops-v3/src/client/mod.rs | 64 ++++++++++++------- .../rust-server/output/ops-v3/src/lib.rs | 9 +-- .../Cargo.toml | 21 ++++-- .../examples/client/main.rs | 4 +- .../examples/server/main.rs | 30 ++------- .../examples/server/server.rs | 63 +++++++++++------- .../src/client/mod.rs | 64 ++++++++++++------- .../src/lib.rs | 9 +-- .../output/rust-server-test/Cargo.toml | 21 ++++-- .../rust-server-test/examples/client/main.rs | 4 +- .../rust-server-test/examples/server/main.rs | 30 ++------- .../examples/server/server.rs | 63 +++++++++++------- .../output/rust-server-test/src/client/mod.rs | 64 ++++++++++++------- .../output/rust-server-test/src/lib.rs | 9 +-- 40 files changed, 773 insertions(+), 574 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/rust-server/Cargo.mustache b/modules/openapi-generator/src/main/resources/rust-server/Cargo.mustache index 014abc865cf..811d44a9fb5 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/Cargo.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/Cargo.mustache @@ -23,9 +23,9 @@ client = [ "serde_urlencoded", {{/usesUrlEncodedForm}} {{#hasCallbacks}} - "tokio-tls", "regex", "percent-encoding", "lazy_static", + "regex", "percent-encoding", "lazy_static", {{/hasCallbacks}} - "serde_json", "serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio", "url" + "serde_json", "serde_ignored", "hyper", "hyper-openssl", "native-tls", "openssl", "tokio", "url" ] server = [ {{#apiUsesMultipart}} @@ -37,16 +37,26 @@ server = [ {{#apiUsesMultipartRelated}} "hyper_0_10", "mime_multipart", {{/apiUsesMultipartRelated}} +{{#hasCallbacks}} + "native-tls", "hyper-openssl", "openssl", +{{/hasCallbacks}} {{! Anything added to the list below, should probably be added to the callbacks list above }} - "serde_json", "serde_ignored", "hyper", "native-tls", "openssl", "tokio", "tokio-tls", "regex", "percent-encoding", "url", "lazy_static" + "serde_json", "serde_ignored", "hyper", "tokio", "regex", "percent-encoding", "url", "lazy_static" ] conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk-enum-derive"] +[target.'cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))'.dependencies] +native-tls = { version = "0.2", optional = true } + +[target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dependencies] +hyper-openssl = { version = "0.7.1", optional = true } +openssl = {version = "0.10", optional = true } + [dependencies] # Common chrono = { version = "0.4", features = ["serde"] } futures = "0.1" -swagger = "3.0" +swagger = "4.0" log = "0.3.0" mime = "0.3" @@ -71,13 +81,10 @@ uuid = {version = "0.7", features = ["serde", "v4"]} # Common between server and client features hyper = {version = "0.12", optional = true} -hyper-tls = {version = "0.2.1", optional = true} {{#apiUsesMultipartRelated}} mime_multipart = {version = "0.5", optional = true} hyper_0_10 = {package = "hyper", version = "0.10", default-features = false, optional=true} {{/apiUsesMultipartRelated}} -native-tls = {version = "0.1.4", optional = true} -openssl = {version = "0.9.14", optional = true} serde_json = {version = "1.0", optional = true} serde_ignored = {version = "0.0.4", optional = true} tokio = {version = "0.1.17", optional = true} @@ -92,7 +99,6 @@ serde_urlencoded = {version = "0.5.1", optional = true} lazy_static = { version = "1.4", optional = true } percent-encoding = {version = "1.0.0", optional = true} regex = {version = "0.2", optional = true} -tokio-tls = {version = "0.1.3", optional = true} # Conversion frunk = { version = "0.3.0", optional = true } @@ -109,6 +115,10 @@ env_logger = "0.6" uuid = {version = "0.7", features = ["serde", "v4"]} {{/apiUsesUuid}} +[target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dev-dependencies] +tokio-openssl = "0.3" +openssl = "0.10" + [[example]] name = "client" required-features = ["client"] diff --git a/modules/openapi-generator/src/main/resources/rust-server/client-imports.mustache b/modules/openapi-generator/src/main/resources/rust-server/client-imports.mustache index edd363156e2..618b5c26457 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/client-imports.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/client-imports.mustache @@ -4,7 +4,8 @@ use hyper; use hyper::client::HttpConnector; use hyper::header::{HeaderName, HeaderValue, CONTENT_TYPE}; use hyper::{Body, Uri, Response}; -use hyper_tls::HttpsConnector; +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +use hyper_openssl::HttpsConnector; use serde_json; use std::borrow::Cow; #[allow(unused_imports)] @@ -18,9 +19,7 @@ use std::str; use std::str::FromStr; use std::string::ToString; use swagger; -use swagger::client::Service; -use swagger::connector; -use swagger::{ApiError, XSpanIdString, Has, AuthData}; +use swagger::{ApiError, Connector, client::Service, XSpanIdString, Has, AuthData}; use url::form_urlencoded; use url::percent_encoding::{utf8_percent_encode, PATH_SEGMENT_ENCODE_SET, QUERY_ENCODE_SET}; {{#apiUsesMultipartFormData}} diff --git a/modules/openapi-generator/src/main/resources/rust-server/client-mod.mustache b/modules/openapi-generator/src/main/resources/rust-server/client-mod.mustache index 9ee06d3cb28..5bd0071fad3 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/client-mod.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/client-mod.mustache @@ -59,8 +59,7 @@ impl Client /// /// Intended for use with custom implementations of connect for e.g. protocol logging /// or similar functionality which requires wrapping the transport layer. When wrapping a TCP connection, - /// this function should be used in conjunction with - /// `swagger::{http_connector, https_connector, https_mutual_connector}`. + /// this function should be used in conjunction with `swagger::Connector::builder()`. /// /// For ordinary tcp connections, prefer the use of `try_new_http`, `try_new_https` /// and `try_new_https_mutual`, to avoid introducing a dependency on the underlying transport layer. @@ -69,18 +68,16 @@ impl Client /// /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" /// * `protocol` - Which protocol to use when constructing the request url, e.g. `Some("http")` - /// * `connector_fn` - Function which returns an implementation of `hyper::client::Connect` + /// * `connector` - Implementation of `hyper::client::Connect` to use for the client pub fn try_new_with_connector( base_path: &str, protocol: Option<&'static str>, - connector_fn: Box C + Send + Sync>, + connector: C, ) -> Result where C: hyper::client::connect::Connect + 'static, C::Transport: 'static, C::Future: 'static, { - let connector = connector_fn(); - let client_service = Box::new(hyper::client::Client::builder().build(connector)); Ok(Client { @@ -96,24 +93,42 @@ impl Client pub fn try_new_http( base_path: &str, ) -> Result { - let http_connector = connector::http_connector(); + let http_connector = Connector::builder().build(); Self::try_new_with_connector(base_path, Some("http"), http_connector) } - /// Create a client with a TLS connection to the server. + /// Create a client with a TLS connection to the server + /// + /// # Arguments + /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" + pub fn try_new_https(base_path: &str) -> Result + { + let https_connector = Connector::builder() + .https() + .build() + .map_err(|e| ClientInitError::SslError(e))?; + Self::try_new_with_connector(base_path, Some("https"), https_connector) + } + + /// Create a client with a TLS connection to the server using a pinned certificate /// /// # Arguments /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" /// * `ca_certificate` - Path to CA certificate used to authenticate the server - pub fn try_new_https( + #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] + pub fn try_new_https_pinned( base_path: &str, ca_certificate: CA, ) -> Result where CA: AsRef, { - let https_connector = connector::https_connector(ca_certificate); + let https_connector = Connector::builder() + .https() + .pin_server_certificate(ca_certificate) + .build() + .map_err(|e| ClientInitError::SslError(e))?; Self::try_new_with_connector(base_path, Some("https"), https_connector) } @@ -124,6 +139,7 @@ impl Client /// * `ca_certificate` - Path to CA certificate used to authenticate the server /// * `client_key` - Path to the client private key /// * `client_certificate` - Path to the client's public certificate associated with the private key + #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] pub fn try_new_https_mutual( base_path: &str, ca_certificate: CA, @@ -135,8 +151,12 @@ impl Client K: AsRef, D: AsRef, { - let https_connector = - connector::https_mutual_connector(ca_certificate, client_key, client_certificate); + let https_connector = Connector::builder() + .https() + .pin_server_certificate(ca_certificate) + .client_authentication(client_key, client_certificate) + .build() + .map_err(|e| ClientInitError::SslError(e))?; Self::try_new_with_connector(base_path, Some("https"), https_connector) } } @@ -170,7 +190,12 @@ pub enum ClientInitError { MissingHost, /// SSL Connection Error - SslError(openssl::error::ErrorStack) + #[cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))] + SslError(native_tls::Error), + + /// SSL Connection Error + #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] + SslError(openssl::error::ErrorStack), } impl From for ClientInitError { @@ -179,12 +204,6 @@ impl From for ClientInitError { } } -impl From for ClientInitError { - fn from(err: openssl::error::ErrorStack) -> ClientInitError { - ClientInitError::SslError(err) - } -} - impl fmt::Display for ClientInitError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let s: &dyn fmt::Debug = self; diff --git a/modules/openapi-generator/src/main/resources/rust-server/example-client-main.mustache b/modules/openapi-generator/src/main/resources/rust-server/example-client-main.mustache index 8c76543d05d..12b3c3126f0 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/example-client-main.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/example-client-main.mustache @@ -13,13 +13,15 @@ extern crate chrono; #[macro_use] extern crate error_chain; extern crate hyper; -extern crate openssl; -extern crate native_tls; -extern crate tokio_tls; {{#apiUsesUuid}} extern crate uuid; {{/apiUsesUuid}} +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +extern crate openssl; +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +extern crate tokio_openssl; + mod server; {{/hasCallbacks}} @@ -79,9 +81,7 @@ fn main() { let client = if matches.is_present("https") { // Using Simple HTTPS - Client::try_new_https( - &base_url, - "examples/ca.pem") + Client::try_new_https(&base_url) .expect("Failed to create HTTPS client") } else { // Using HTTP @@ -99,7 +99,7 @@ fn main() { {{#hasCallbacks}} // We could do HTTPS here, but for simplicity we don't - rt.spawn(server::create("127.0.0.1:8081", None)); + rt.spawn(server::create("127.0.0.1:8081", false)); {{/hasCallbacks}} match matches.value_of("operation") { diff --git a/modules/openapi-generator/src/main/resources/rust-server/example-server-common.mustache b/modules/openapi-generator/src/main/resources/rust-server/example-server-common.mustache index 351596808fc..19f104593a6 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/example-server-common.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/example-server-common.mustache @@ -12,7 +12,6 @@ use chrono; use futures::{future, Future, Stream}; use hyper::server::conn::Http; use hyper::service::MakeService as _; -use native_tls; use openssl::ssl::SslAcceptorBuilder; use std::collections::HashMap; use std::marker::PhantomData; @@ -23,12 +22,18 @@ use swagger::{Has, XSpanIdString}; use swagger::auth::MakeAllowAllAuthenticator; use swagger::EmptyContext; use tokio::net::TcpListener; -use tokio_tls::TlsAcceptorExt; {{#apiUsesUuid}}use uuid;{{/apiUsesUuid}} +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +use tokio_openssl::SslAcceptorExt; +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod}; + use {{{externCrateName}}}::models; -pub fn create(addr: &str, https: Option) -> Box + Send> { +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +/// Builds an SSL implementation for Simple HTTPS from some hard-coded file names +pub fn create(addr: &str, https: bool) -> Box + Send> { let addr = addr.parse().expect("Failed to parse bind address"); let server = Server::new(); @@ -42,30 +47,44 @@ pub fn create(addr: &str, https: Option) -> Box Result { - let mut ssl = SslAcceptorBuilder::mozilla_intermediate_raw(SslMethod::tls())?; - - // Server authentication - ssl.set_private_key_file("examples/server-key.pem", X509_FILETYPE_PEM)?; - ssl.set_certificate_chain_file("examples/server-chain.pem")?; - ssl.check_private_key()?; - - Ok(ssl) -} /// Create custom server, wire it to the autogenerated router, /// and pass it to the web server. @@ -59,11 +47,5 @@ fn main() { let addr = "127.0.0.1:{{{serverPort}}}"; - let https = if matches.is_present("https") { - Some(ssl().expect("Failed to load SSL keys")) - } else { - None - }; - - hyper::rt::run(server::create(addr, https)); + hyper::rt::run(server::create(addr, matches.is_present("https"))); } diff --git a/modules/openapi-generator/src/main/resources/rust-server/lib.mustache b/modules/openapi-generator/src/main/resources/rust-server/lib.mustache index 57daa59a069..61159b38083 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/lib.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/lib.mustache @@ -41,10 +41,14 @@ extern crate swagger; #[cfg(any(feature = "client", feature = "server"))] extern crate hyper; -#[cfg(feature = "client")] -extern crate hyper_tls; +{{#hasCallbacks}} #[cfg(any(feature = "client", feature = "server"))] -extern crate openssl; +{{/hasCallbacks}} +{{^hasCallbacks}} +#[cfg(feature = "server")] +{{/hasCallbacks}} +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +extern crate hyper_openssl; {{#apiUsesMultipart}} #[cfg(any(feature = "client", feature = "server"))] extern crate mime_0_2; @@ -53,8 +57,6 @@ extern crate mime_0_2; #[cfg(any(feature = "client", feature = "server"))] extern crate mime_multipart; {{/apiUsesMultipartRelated}} -#[cfg(any(feature = "client", feature = "server"))] -extern crate native_tls; {{#hasCallbacks}} #[cfg(any(feature = "client", feature = "server"))] {{/hasCallbacks}} diff --git a/modules/openapi-generator/src/main/resources/rust-server/server-callbacks.mustache b/modules/openapi-generator/src/main/resources/rust-server/server-callbacks.mustache index 8b407a9022c..e3b29f0e364 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/server-callbacks.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/server-callbacks.mustache @@ -45,24 +45,21 @@ impl Client /// /// Intended for use with custom implementations of connect for e.g. protocol logging /// or similar functionality which requires wrapping the transport layer. When wrapping a TCP connection, - /// this function should be used in conjunction with - /// `swagger::{http_connector, https_connector, https_mutual_connector}`. + /// this function should be used in conjunction with `swagger::Connector::builder()`. /// /// For ordinary tcp connections, prefer the use of `new_http`, `new_https` /// and `new_https_mutual`, to avoid introducing a dependency on the underlying transport layer. /// /// # Arguments /// - /// * `connector_fn` - Function which returns an implementation of `hyper::client::Connect` + /// * `connector` - Implementation of `hyper::client::Connect` to use for the client pub fn new_with_connector( - connector_fn: Box C + Send + Sync>, + connector: C, ) -> Self where C: hyper::client::connect::Connect + 'static, C::Transport: 'static, C::Future: 'static, { - let connector = connector_fn(); - let client_service = Box::new(hyper::client::Client::builder().build(connector)); Client { @@ -72,21 +69,41 @@ impl Client /// Create an HTTP client. pub fn new_http() -> Self { - let http_connector = connector::http_connector(); + let http_connector = Connector::builder().build(); Self::new_with_connector(http_connector) } /// Create a client with a TLS connection to the server. + #[cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))] + pub fn new_https() -> Result + { + let https_connector = Connector::builder().https().build()?; + Ok(Self::new_with_connector(https_connector)) + } + + /// Create a client with a TLS connection to the server. + #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] + pub fn new_https() -> Result + { + let https_connector = Connector::builder().https().build()?; + Ok(Self::new_with_connector(https_connector)) + } + + /// Create a client with a TLS connection to the server, pinning the certificate /// /// # Arguments /// * `ca_certificate` - Path to CA certificate used to authenticate the server - pub fn new_https( + #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] + pub fn new_https_pinned( ca_certificate: CA, - ) -> Self where + ) -> Result where CA: AsRef, { - let https_connector = connector::https_connector(ca_certificate); - Self::new_with_connector(https_connector) + let https_connector = Connector::builder() + .https() + .pin_server_certificate(ca_certificate) + .build()?; + Ok(Self::new_with_connector(https_connector)) } /// Create a client with a mutually authenticated TLS connection to the server. @@ -95,19 +112,23 @@ impl Client /// * `ca_certificate` - Path to CA certificate used to authenticate the server /// * `client_key` - Path to the client private key /// * `client_certificate` - Path to the client's public certificate associated with the private key + #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] pub fn new_https_mutual( ca_certificate: CA, client_key: K, client_certificate: D, - ) -> Self + ) -> Result where CA: AsRef, K: AsRef, D: AsRef, { - let https_connector = - connector::https_mutual_connector(ca_certificate, client_key, client_certificate); - Self::new_with_connector(https_connector) + let https_connector = Connector::builder() + .https() + .pin_server_certificate(ca_certificate) + .client_authentication(client_key, client_certificate) + .build()?; + Ok(Self::new_with_connector(https_connector)) } } diff --git a/samples/server/petstore/rust-server/output/multipart-v3/Cargo.toml b/samples/server/petstore/rust-server/output/multipart-v3/Cargo.toml index d80023654b4..119b68ea7e8 100644 --- a/samples/server/petstore/rust-server/output/multipart-v3/Cargo.toml +++ b/samples/server/petstore/rust-server/output/multipart-v3/Cargo.toml @@ -11,21 +11,28 @@ client = [ "mime_0_2", "multipart", "multipart/client", "swagger/multipart", "hyper_0_10", "mime_multipart", - "serde_json", "serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio", "url" + "serde_json", "serde_ignored", "hyper", "hyper-openssl", "native-tls", "openssl", "tokio", "url" ] server = [ "mime_0_2", "multipart", "multipart/server", "hyper_0_10", "mime_multipart", - "serde_json", "serde_ignored", "hyper", "native-tls", "openssl", "tokio", "tokio-tls", "regex", "percent-encoding", "url", "lazy_static" + "serde_json", "serde_ignored", "hyper", "tokio", "regex", "percent-encoding", "url", "lazy_static" ] conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk-enum-derive"] +[target.'cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))'.dependencies] +native-tls = { version = "0.2", optional = true } + +[target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dependencies] +hyper-openssl = { version = "0.7.1", optional = true } +openssl = {version = "0.10", optional = true } + [dependencies] # Common chrono = { version = "0.4", features = ["serde"] } futures = "0.1" -swagger = "3.0" +swagger = "4.0" log = "0.3.0" mime = "0.3" @@ -38,11 +45,8 @@ multipart = { version = "0.16", default-features = false, optional = true } # Common between server and client features hyper = {version = "0.12", optional = true} -hyper-tls = {version = "0.2.1", optional = true} mime_multipart = {version = "0.5", optional = true} hyper_0_10 = {package = "hyper", version = "0.10", default-features = false, optional=true} -native-tls = {version = "0.1.4", optional = true} -openssl = {version = "0.9.14", optional = true} serde_json = {version = "1.0", optional = true} serde_ignored = {version = "0.0.4", optional = true} tokio = {version = "0.1.17", optional = true} @@ -54,7 +58,6 @@ url = {version = "1.5", optional = true} lazy_static = { version = "1.4", optional = true } percent-encoding = {version = "1.0.0", optional = true} regex = {version = "0.2", optional = true} -tokio-tls = {version = "0.1.3", optional = true} # Conversion frunk = { version = "0.3.0", optional = true } @@ -69,6 +72,10 @@ error-chain = "0.12" env_logger = "0.6" uuid = {version = "0.7", features = ["serde", "v4"]} +[target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dev-dependencies] +tokio-openssl = "0.3" +openssl = "0.10" + [[example]] name = "client" required-features = ["client"] diff --git a/samples/server/petstore/rust-server/output/multipart-v3/examples/client/main.rs b/samples/server/petstore/rust-server/output/multipart-v3/examples/client/main.rs index 90c66a58905..296a69048eb 100644 --- a/samples/server/petstore/rust-server/output/multipart-v3/examples/client/main.rs +++ b/samples/server/petstore/rust-server/output/multipart-v3/examples/client/main.rs @@ -55,9 +55,7 @@ fn main() { let client = if matches.is_present("https") { // Using Simple HTTPS - Client::try_new_https( - &base_url, - "examples/ca.pem") + Client::try_new_https(&base_url) .expect("Failed to create HTTPS client") } else { // Using HTTP diff --git a/samples/server/petstore/rust-server/output/multipart-v3/examples/server/main.rs b/samples/server/petstore/rust-server/output/multipart-v3/examples/server/main.rs index f807b14ab40..026a3018165 100644 --- a/samples/server/petstore/rust-server/output/multipart-v3/examples/server/main.rs +++ b/samples/server/petstore/rust-server/output/multipart-v3/examples/server/main.rs @@ -10,7 +10,6 @@ extern crate env_logger; extern crate hyper; #[macro_use] extern crate log; -extern crate openssl; extern crate swagger; // Imports required by server library. @@ -19,29 +18,18 @@ extern crate chrono; #[macro_use] extern crate error_chain; extern crate futures; -extern crate native_tls; // extern crate swagger; extern crate tokio; -extern crate tokio_tls; + +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +extern crate openssl; +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +extern crate tokio_openssl; use clap::{App, Arg}; -use openssl::x509::X509_FILETYPE_PEM; -use openssl::ssl::{SslAcceptorBuilder, SslMethod}; -use openssl::error::ErrorStack; mod server; -// Builds an SSL implementation for Simple HTTPS from some hard-coded file names -fn ssl() -> Result { - let mut ssl = SslAcceptorBuilder::mozilla_intermediate_raw(SslMethod::tls())?; - - // Server authentication - ssl.set_private_key_file("examples/server-key.pem", X509_FILETYPE_PEM)?; - ssl.set_certificate_chain_file("examples/server-chain.pem")?; - ssl.check_private_key()?; - - Ok(ssl) -} /// Create custom server, wire it to the autogenerated router, /// and pass it to the web server. @@ -56,11 +44,5 @@ fn main() { let addr = "127.0.0.1:80"; - let https = if matches.is_present("https") { - Some(ssl().expect("Failed to load SSL keys")) - } else { - None - }; - - hyper::rt::run(server::create(addr, https)); + hyper::rt::run(server::create(addr, matches.is_present("https"))); } diff --git a/samples/server/petstore/rust-server/output/multipart-v3/examples/server/server.rs b/samples/server/petstore/rust-server/output/multipart-v3/examples/server/server.rs index 67334139800..1fb5a1f7095 100644 --- a/samples/server/petstore/rust-server/output/multipart-v3/examples/server/server.rs +++ b/samples/server/petstore/rust-server/output/multipart-v3/examples/server/server.rs @@ -12,7 +12,6 @@ use chrono; use futures::{future, Future, Stream}; use hyper::server::conn::Http; use hyper::service::MakeService as _; -use native_tls; use openssl::ssl::SslAcceptorBuilder; use std::collections::HashMap; use std::marker::PhantomData; @@ -23,12 +22,18 @@ use swagger::{Has, XSpanIdString}; use swagger::auth::MakeAllowAllAuthenticator; use swagger::EmptyContext; use tokio::net::TcpListener; -use tokio_tls::TlsAcceptorExt; +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +use tokio_openssl::SslAcceptorExt; +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod}; + use multipart_v3::models; -pub fn create(addr: &str, https: Option) -> Box + Send> { +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +/// Builds an SSL implementation for Simple HTTPS from some hard-coded file names +pub fn create(addr: &str, https: bool) -> Box + Send> { let addr = addr.parse().expect("Failed to parse bind address"); let server = Server::new(); @@ -42,30 +47,44 @@ pub fn create(addr: &str, https: Option) -> Box /// /// Intended for use with custom implementations of connect for e.g. protocol logging /// or similar functionality which requires wrapping the transport layer. When wrapping a TCP connection, - /// this function should be used in conjunction with - /// `swagger::{http_connector, https_connector, https_mutual_connector}`. + /// this function should be used in conjunction with `swagger::Connector::builder()`. /// /// For ordinary tcp connections, prefer the use of `try_new_http`, `try_new_https` /// and `try_new_https_mutual`, to avoid introducing a dependency on the underlying transport layer. @@ -109,18 +107,16 @@ impl Client /// /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" /// * `protocol` - Which protocol to use when constructing the request url, e.g. `Some("http")` - /// * `connector_fn` - Function which returns an implementation of `hyper::client::Connect` + /// * `connector` - Implementation of `hyper::client::Connect` to use for the client pub fn try_new_with_connector( base_path: &str, protocol: Option<&'static str>, - connector_fn: Box C + Send + Sync>, + connector: C, ) -> Result where C: hyper::client::connect::Connect + 'static, C::Transport: 'static, C::Future: 'static, { - let connector = connector_fn(); - let client_service = Box::new(hyper::client::Client::builder().build(connector)); Ok(Client { @@ -136,24 +132,42 @@ impl Client pub fn try_new_http( base_path: &str, ) -> Result { - let http_connector = connector::http_connector(); + let http_connector = Connector::builder().build(); Self::try_new_with_connector(base_path, Some("http"), http_connector) } - /// Create a client with a TLS connection to the server. + /// Create a client with a TLS connection to the server + /// + /// # Arguments + /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" + pub fn try_new_https(base_path: &str) -> Result + { + let https_connector = Connector::builder() + .https() + .build() + .map_err(|e| ClientInitError::SslError(e))?; + Self::try_new_with_connector(base_path, Some("https"), https_connector) + } + + /// Create a client with a TLS connection to the server using a pinned certificate /// /// # Arguments /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" /// * `ca_certificate` - Path to CA certificate used to authenticate the server - pub fn try_new_https( + #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] + pub fn try_new_https_pinned( base_path: &str, ca_certificate: CA, ) -> Result where CA: AsRef, { - let https_connector = connector::https_connector(ca_certificate); + let https_connector = Connector::builder() + .https() + .pin_server_certificate(ca_certificate) + .build() + .map_err(|e| ClientInitError::SslError(e))?; Self::try_new_with_connector(base_path, Some("https"), https_connector) } @@ -164,6 +178,7 @@ impl Client /// * `ca_certificate` - Path to CA certificate used to authenticate the server /// * `client_key` - Path to the client private key /// * `client_certificate` - Path to the client's public certificate associated with the private key + #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] pub fn try_new_https_mutual( base_path: &str, ca_certificate: CA, @@ -175,8 +190,12 @@ impl Client K: AsRef, D: AsRef, { - let https_connector = - connector::https_mutual_connector(ca_certificate, client_key, client_certificate); + let https_connector = Connector::builder() + .https() + .pin_server_certificate(ca_certificate) + .client_authentication(client_key, client_certificate) + .build() + .map_err(|e| ClientInitError::SslError(e))?; Self::try_new_with_connector(base_path, Some("https"), https_connector) } } @@ -210,7 +229,12 @@ pub enum ClientInitError { MissingHost, /// SSL Connection Error - SslError(openssl::error::ErrorStack) + #[cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))] + SslError(native_tls::Error), + + /// SSL Connection Error + #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] + SslError(openssl::error::ErrorStack), } impl From for ClientInitError { @@ -219,12 +243,6 @@ impl From for ClientInitError { } } -impl From for ClientInitError { - fn from(err: openssl::error::ErrorStack) -> ClientInitError { - ClientInitError::SslError(err) - } -} - impl fmt::Display for ClientInitError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let s: &dyn fmt::Debug = self; diff --git a/samples/server/petstore/rust-server/output/multipart-v3/src/lib.rs b/samples/server/petstore/rust-server/output/multipart-v3/src/lib.rs index 8ec1230b3bc..bb8edc5d76c 100644 --- a/samples/server/petstore/rust-server/output/multipart-v3/src/lib.rs +++ b/samples/server/petstore/rust-server/output/multipart-v3/src/lib.rs @@ -34,16 +34,13 @@ extern crate swagger; #[cfg(any(feature = "client", feature = "server"))] extern crate hyper; -#[cfg(feature = "client")] -extern crate hyper_tls; -#[cfg(any(feature = "client", feature = "server"))] -extern crate openssl; +#[cfg(feature = "server")] +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +extern crate hyper_openssl; #[cfg(any(feature = "client", feature = "server"))] extern crate mime_0_2; #[cfg(any(feature = "client", feature = "server"))] extern crate mime_multipart; -#[cfg(any(feature = "client", feature = "server"))] -extern crate native_tls; #[cfg(feature = "server")] extern crate percent_encoding; #[cfg(any(feature = "client", feature = "server"))] diff --git a/samples/server/petstore/rust-server/output/openapi-v3/Cargo.toml b/samples/server/petstore/rust-server/output/openapi-v3/Cargo.toml index 318ff18de52..a0df7ec420c 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/Cargo.toml +++ b/samples/server/petstore/rust-server/output/openapi-v3/Cargo.toml @@ -8,19 +8,27 @@ license = "Unlicense" [features] default = ["client", "server"] client = [ - "tokio-tls", "regex", "percent-encoding", "lazy_static", - "serde_json", "serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio", "url" + "regex", "percent-encoding", "lazy_static", + "serde_json", "serde_ignored", "hyper", "hyper-openssl", "native-tls", "openssl", "tokio", "url" ] server = [ - "serde_json", "serde_ignored", "hyper", "native-tls", "openssl", "tokio", "tokio-tls", "regex", "percent-encoding", "url", "lazy_static" + "native-tls", "hyper-openssl", "openssl", + "serde_json", "serde_ignored", "hyper", "tokio", "regex", "percent-encoding", "url", "lazy_static" ] conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk-enum-derive"] +[target.'cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))'.dependencies] +native-tls = { version = "0.2", optional = true } + +[target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dependencies] +hyper-openssl = { version = "0.7.1", optional = true } +openssl = {version = "0.10", optional = true } + [dependencies] # Common chrono = { version = "0.4", features = ["serde"] } futures = "0.1" -swagger = "3.0" +swagger = "4.0" log = "0.3.0" mime = "0.3" @@ -35,9 +43,6 @@ uuid = {version = "0.7", features = ["serde", "v4"]} # Common between server and client features hyper = {version = "0.12", optional = true} -hyper-tls = {version = "0.2.1", optional = true} -native-tls = {version = "0.1.4", optional = true} -openssl = {version = "0.9.14", optional = true} serde_json = {version = "1.0", optional = true} serde_ignored = {version = "0.0.4", optional = true} tokio = {version = "0.1.17", optional = true} @@ -49,7 +54,6 @@ url = {version = "1.5", optional = true} lazy_static = { version = "1.4", optional = true } percent-encoding = {version = "1.0.0", optional = true} regex = {version = "0.2", optional = true} -tokio-tls = {version = "0.1.3", optional = true} # Conversion frunk = { version = "0.3.0", optional = true } @@ -63,6 +67,10 @@ clap = "2.25" error-chain = "0.12" env_logger = "0.6" +[target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dev-dependencies] +tokio-openssl = "0.3" +openssl = "0.10" + [[example]] name = "client" required-features = ["client"] diff --git a/samples/server/petstore/rust-server/output/openapi-v3/examples/client/main.rs b/samples/server/petstore/rust-server/output/openapi-v3/examples/client/main.rs index d443f693844..e6a88cec7f8 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/examples/client/main.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/examples/client/main.rs @@ -12,11 +12,13 @@ extern crate chrono; #[macro_use] extern crate error_chain; extern crate hyper; -extern crate openssl; -extern crate native_tls; -extern crate tokio_tls; extern crate uuid; +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +extern crate openssl; +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +extern crate tokio_openssl; + mod server; #[allow(unused_imports)] @@ -98,9 +100,7 @@ fn main() { let client = if matches.is_present("https") { // Using Simple HTTPS - Client::try_new_https( - &base_url, - "examples/ca.pem") + Client::try_new_https(&base_url) .expect("Failed to create HTTPS client") } else { // Using HTTP @@ -117,7 +117,7 @@ fn main() { let mut rt = tokio::runtime::Runtime::new().unwrap(); // We could do HTTPS here, but for simplicity we don't - rt.spawn(server::create("127.0.0.1:8081", None)); + rt.spawn(server::create("127.0.0.1:8081", false)); match matches.value_of("operation") { Some("CallbackWithHeaderPost") => { diff --git a/samples/server/petstore/rust-server/output/openapi-v3/examples/client/server.rs b/samples/server/petstore/rust-server/output/openapi-v3/examples/client/server.rs index c58b9da8bbc..0af97f30412 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/examples/client/server.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/examples/client/server.rs @@ -12,7 +12,6 @@ use chrono; use futures::{future, Future, Stream}; use hyper::server::conn::Http; use hyper::service::MakeService as _; -use native_tls; use openssl::ssl::SslAcceptorBuilder; use std::collections::HashMap; use std::marker::PhantomData; @@ -23,12 +22,18 @@ use swagger::{Has, XSpanIdString}; use swagger::auth::MakeAllowAllAuthenticator; use swagger::EmptyContext; use tokio::net::TcpListener; -use tokio_tls::TlsAcceptorExt; use uuid; +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +use tokio_openssl::SslAcceptorExt; +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod}; + use openapi_v3::models; -pub fn create(addr: &str, https: Option) -> Box + Send> { +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +/// Builds an SSL implementation for Simple HTTPS from some hard-coded file names +pub fn create(addr: &str, https: bool) -> Box + Send> { let addr = addr.parse().expect("Failed to parse bind address"); let server = Server::new(); @@ -42,30 +47,44 @@ pub fn create(addr: &str, https: Option) -> Box Result { - let mut ssl = SslAcceptorBuilder::mozilla_intermediate_raw(SslMethod::tls())?; - - // Server authentication - ssl.set_private_key_file("examples/server-key.pem", X509_FILETYPE_PEM)?; - ssl.set_certificate_chain_file("examples/server-chain.pem")?; - ssl.check_private_key()?; - - Ok(ssl) -} /// Create custom server, wire it to the autogenerated router, /// and pass it to the web server. @@ -57,11 +45,5 @@ fn main() { let addr = "127.0.0.1:80"; - let https = if matches.is_present("https") { - Some(ssl().expect("Failed to load SSL keys")) - } else { - None - }; - - hyper::rt::run(server::create(addr, https)); + hyper::rt::run(server::create(addr, matches.is_present("https"))); } diff --git a/samples/server/petstore/rust-server/output/openapi-v3/examples/server/server.rs b/samples/server/petstore/rust-server/output/openapi-v3/examples/server/server.rs index c87bc45e4ad..0b32ac09425 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/examples/server/server.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/examples/server/server.rs @@ -12,7 +12,6 @@ use chrono; use futures::{future, Future, Stream}; use hyper::server::conn::Http; use hyper::service::MakeService as _; -use native_tls; use openssl::ssl::SslAcceptorBuilder; use std::collections::HashMap; use std::marker::PhantomData; @@ -23,12 +22,18 @@ use swagger::{Has, XSpanIdString}; use swagger::auth::MakeAllowAllAuthenticator; use swagger::EmptyContext; use tokio::net::TcpListener; -use tokio_tls::TlsAcceptorExt; use uuid; +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +use tokio_openssl::SslAcceptorExt; +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod}; + use openapi_v3::models; -pub fn create(addr: &str, https: Option) -> Box + Send> { +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +/// Builds an SSL implementation for Simple HTTPS from some hard-coded file names +pub fn create(addr: &str, https: bool) -> Box + Send> { let addr = addr.parse().expect("Failed to parse bind address"); let server = Server::new(); @@ -42,30 +47,44 @@ pub fn create(addr: &str, https: Option) -> Box /// /// Intended for use with custom implementations of connect for e.g. protocol logging /// or similar functionality which requires wrapping the transport layer. When wrapping a TCP connection, - /// this function should be used in conjunction with - /// `swagger::{http_connector, https_connector, https_mutual_connector}`. + /// this function should be used in conjunction with `swagger::Connector::builder()`. /// /// For ordinary tcp connections, prefer the use of `try_new_http`, `try_new_https` /// and `try_new_https_mutual`, to avoid introducing a dependency on the underlying transport layer. @@ -124,18 +122,16 @@ impl Client /// /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" /// * `protocol` - Which protocol to use when constructing the request url, e.g. `Some("http")` - /// * `connector_fn` - Function which returns an implementation of `hyper::client::Connect` + /// * `connector` - Implementation of `hyper::client::Connect` to use for the client pub fn try_new_with_connector( base_path: &str, protocol: Option<&'static str>, - connector_fn: Box C + Send + Sync>, + connector: C, ) -> Result where C: hyper::client::connect::Connect + 'static, C::Transport: 'static, C::Future: 'static, { - let connector = connector_fn(); - let client_service = Box::new(hyper::client::Client::builder().build(connector)); Ok(Client { @@ -151,24 +147,42 @@ impl Client pub fn try_new_http( base_path: &str, ) -> Result { - let http_connector = connector::http_connector(); + let http_connector = Connector::builder().build(); Self::try_new_with_connector(base_path, Some("http"), http_connector) } - /// Create a client with a TLS connection to the server. + /// Create a client with a TLS connection to the server + /// + /// # Arguments + /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" + pub fn try_new_https(base_path: &str) -> Result + { + let https_connector = Connector::builder() + .https() + .build() + .map_err(|e| ClientInitError::SslError(e))?; + Self::try_new_with_connector(base_path, Some("https"), https_connector) + } + + /// Create a client with a TLS connection to the server using a pinned certificate /// /// # Arguments /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" /// * `ca_certificate` - Path to CA certificate used to authenticate the server - pub fn try_new_https( + #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] + pub fn try_new_https_pinned( base_path: &str, ca_certificate: CA, ) -> Result where CA: AsRef, { - let https_connector = connector::https_connector(ca_certificate); + let https_connector = Connector::builder() + .https() + .pin_server_certificate(ca_certificate) + .build() + .map_err(|e| ClientInitError::SslError(e))?; Self::try_new_with_connector(base_path, Some("https"), https_connector) } @@ -179,6 +193,7 @@ impl Client /// * `ca_certificate` - Path to CA certificate used to authenticate the server /// * `client_key` - Path to the client private key /// * `client_certificate` - Path to the client's public certificate associated with the private key + #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] pub fn try_new_https_mutual( base_path: &str, ca_certificate: CA, @@ -190,8 +205,12 @@ impl Client K: AsRef, D: AsRef, { - let https_connector = - connector::https_mutual_connector(ca_certificate, client_key, client_certificate); + let https_connector = Connector::builder() + .https() + .pin_server_certificate(ca_certificate) + .client_authentication(client_key, client_certificate) + .build() + .map_err(|e| ClientInitError::SslError(e))?; Self::try_new_with_connector(base_path, Some("https"), https_connector) } } @@ -225,7 +244,12 @@ pub enum ClientInitError { MissingHost, /// SSL Connection Error - SslError(openssl::error::ErrorStack) + #[cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))] + SslError(native_tls::Error), + + /// SSL Connection Error + #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] + SslError(openssl::error::ErrorStack), } impl From for ClientInitError { @@ -234,12 +258,6 @@ impl From for ClientInitError { } } -impl From for ClientInitError { - fn from(err: openssl::error::ErrorStack) -> ClientInitError { - ClientInitError::SslError(err) - } -} - impl fmt::Display for ClientInitError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let s: &dyn fmt::Debug = self; diff --git a/samples/server/petstore/rust-server/output/openapi-v3/src/lib.rs b/samples/server/petstore/rust-server/output/openapi-v3/src/lib.rs index 93e339fed8b..0fcba48f013 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/src/lib.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/src/lib.rs @@ -31,12 +31,9 @@ extern crate swagger; #[cfg(any(feature = "client", feature = "server"))] extern crate hyper; -#[cfg(feature = "client")] -extern crate hyper_tls; #[cfg(any(feature = "client", feature = "server"))] -extern crate openssl; -#[cfg(any(feature = "client", feature = "server"))] -extern crate native_tls; +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +extern crate hyper_openssl; #[cfg(any(feature = "client", feature = "server"))] extern crate percent_encoding; #[cfg(any(feature = "client", feature = "server"))] diff --git a/samples/server/petstore/rust-server/output/openapi-v3/src/server/callbacks.rs b/samples/server/petstore/rust-server/output/openapi-v3/src/server/callbacks.rs index 0bef61b201e..36f52eab18a 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/src/server/callbacks.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/src/server/callbacks.rs @@ -4,7 +4,8 @@ use hyper; use hyper::client::HttpConnector; use hyper::header::{HeaderName, HeaderValue, CONTENT_TYPE}; use hyper::{Body, Uri, Response}; -use hyper_tls::HttpsConnector; +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +use hyper_openssl::HttpsConnector; use serde_json; use std::borrow::Cow; #[allow(unused_imports)] @@ -18,9 +19,7 @@ use std::str; use std::str::FromStr; use std::string::ToString; use swagger; -use swagger::client::Service; -use swagger::connector; -use swagger::{ApiError, XSpanIdString, Has, AuthData}; +use swagger::{ApiError, Connector, client::Service, XSpanIdString, Has, AuthData}; use url::form_urlencoded; use url::percent_encoding::{utf8_percent_encode, PATH_SEGMENT_ENCODE_SET, QUERY_ENCODE_SET}; use uuid; @@ -71,24 +70,21 @@ impl Client /// /// Intended for use with custom implementations of connect for e.g. protocol logging /// or similar functionality which requires wrapping the transport layer. When wrapping a TCP connection, - /// this function should be used in conjunction with - /// `swagger::{http_connector, https_connector, https_mutual_connector}`. + /// this function should be used in conjunction with `swagger::Connector::builder()`. /// /// For ordinary tcp connections, prefer the use of `new_http`, `new_https` /// and `new_https_mutual`, to avoid introducing a dependency on the underlying transport layer. /// /// # Arguments /// - /// * `connector_fn` - Function which returns an implementation of `hyper::client::Connect` + /// * `connector` - Implementation of `hyper::client::Connect` to use for the client pub fn new_with_connector( - connector_fn: Box C + Send + Sync>, + connector: C, ) -> Self where C: hyper::client::connect::Connect + 'static, C::Transport: 'static, C::Future: 'static, { - let connector = connector_fn(); - let client_service = Box::new(hyper::client::Client::builder().build(connector)); Client { @@ -98,21 +94,41 @@ impl Client /// Create an HTTP client. pub fn new_http() -> Self { - let http_connector = connector::http_connector(); + let http_connector = Connector::builder().build(); Self::new_with_connector(http_connector) } /// Create a client with a TLS connection to the server. + #[cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))] + pub fn new_https() -> Result + { + let https_connector = Connector::builder().https().build()?; + Ok(Self::new_with_connector(https_connector)) + } + + /// Create a client with a TLS connection to the server. + #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] + pub fn new_https() -> Result + { + let https_connector = Connector::builder().https().build()?; + Ok(Self::new_with_connector(https_connector)) + } + + /// Create a client with a TLS connection to the server, pinning the certificate /// /// # Arguments /// * `ca_certificate` - Path to CA certificate used to authenticate the server - pub fn new_https( + #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] + pub fn new_https_pinned( ca_certificate: CA, - ) -> Self where + ) -> Result where CA: AsRef, { - let https_connector = connector::https_connector(ca_certificate); - Self::new_with_connector(https_connector) + let https_connector = Connector::builder() + .https() + .pin_server_certificate(ca_certificate) + .build()?; + Ok(Self::new_with_connector(https_connector)) } /// Create a client with a mutually authenticated TLS connection to the server. @@ -121,19 +137,23 @@ impl Client /// * `ca_certificate` - Path to CA certificate used to authenticate the server /// * `client_key` - Path to the client private key /// * `client_certificate` - Path to the client's public certificate associated with the private key + #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] pub fn new_https_mutual( ca_certificate: CA, client_key: K, client_certificate: D, - ) -> Self + ) -> Result where CA: AsRef, K: AsRef, D: AsRef, { - let https_connector = - connector::https_mutual_connector(ca_certificate, client_key, client_certificate); - Self::new_with_connector(https_connector) + let https_connector = Connector::builder() + .https() + .pin_server_certificate(ca_certificate) + .client_authentication(client_key, client_certificate) + .build()?; + Ok(Self::new_with_connector(https_connector)) } } diff --git a/samples/server/petstore/rust-server/output/ops-v3/Cargo.toml b/samples/server/petstore/rust-server/output/ops-v3/Cargo.toml index 47100394181..2040087c07a 100644 --- a/samples/server/petstore/rust-server/output/ops-v3/Cargo.toml +++ b/samples/server/petstore/rust-server/output/ops-v3/Cargo.toml @@ -8,18 +8,25 @@ license = "Unlicense" [features] default = ["client", "server"] client = [ - "serde_json", "serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio", "url" + "serde_json", "serde_ignored", "hyper", "hyper-openssl", "native-tls", "openssl", "tokio", "url" ] server = [ - "serde_json", "serde_ignored", "hyper", "native-tls", "openssl", "tokio", "tokio-tls", "regex", "percent-encoding", "url", "lazy_static" + "serde_json", "serde_ignored", "hyper", "tokio", "regex", "percent-encoding", "url", "lazy_static" ] conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk-enum-derive"] +[target.'cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))'.dependencies] +native-tls = { version = "0.2", optional = true } + +[target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dependencies] +hyper-openssl = { version = "0.7.1", optional = true } +openssl = {version = "0.10", optional = true } + [dependencies] # Common chrono = { version = "0.4", features = ["serde"] } futures = "0.1" -swagger = "3.0" +swagger = "4.0" log = "0.3.0" mime = "0.3" @@ -30,9 +37,6 @@ serde_derive = "1.0" # Common between server and client features hyper = {version = "0.12", optional = true} -hyper-tls = {version = "0.2.1", optional = true} -native-tls = {version = "0.1.4", optional = true} -openssl = {version = "0.9.14", optional = true} serde_json = {version = "1.0", optional = true} serde_ignored = {version = "0.0.4", optional = true} tokio = {version = "0.1.17", optional = true} @@ -44,7 +48,6 @@ url = {version = "1.5", optional = true} lazy_static = { version = "1.4", optional = true } percent-encoding = {version = "1.0.0", optional = true} regex = {version = "0.2", optional = true} -tokio-tls = {version = "0.1.3", optional = true} # Conversion frunk = { version = "0.3.0", optional = true } @@ -59,6 +62,10 @@ error-chain = "0.12" env_logger = "0.6" uuid = {version = "0.7", features = ["serde", "v4"]} +[target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dev-dependencies] +tokio-openssl = "0.3" +openssl = "0.10" + [[example]] name = "client" required-features = ["client"] diff --git a/samples/server/petstore/rust-server/output/ops-v3/examples/client/main.rs b/samples/server/petstore/rust-server/output/ops-v3/examples/client/main.rs index 06052931315..2597f3ae6f1 100644 --- a/samples/server/petstore/rust-server/output/ops-v3/examples/client/main.rs +++ b/samples/server/petstore/rust-server/output/ops-v3/examples/client/main.rs @@ -125,9 +125,7 @@ fn main() { let client = if matches.is_present("https") { // Using Simple HTTPS - Client::try_new_https( - &base_url, - "examples/ca.pem") + Client::try_new_https(&base_url) .expect("Failed to create HTTPS client") } else { // Using HTTP diff --git a/samples/server/petstore/rust-server/output/ops-v3/examples/server/main.rs b/samples/server/petstore/rust-server/output/ops-v3/examples/server/main.rs index b754559a702..18204de5c8c 100644 --- a/samples/server/petstore/rust-server/output/ops-v3/examples/server/main.rs +++ b/samples/server/petstore/rust-server/output/ops-v3/examples/server/main.rs @@ -10,7 +10,6 @@ extern crate env_logger; extern crate hyper; #[macro_use] extern crate log; -extern crate openssl; extern crate swagger; // Imports required by server library. @@ -19,29 +18,18 @@ extern crate chrono; #[macro_use] extern crate error_chain; extern crate futures; -extern crate native_tls; // extern crate swagger; extern crate tokio; -extern crate tokio_tls; + +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +extern crate openssl; +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +extern crate tokio_openssl; use clap::{App, Arg}; -use openssl::x509::X509_FILETYPE_PEM; -use openssl::ssl::{SslAcceptorBuilder, SslMethod}; -use openssl::error::ErrorStack; mod server; -// Builds an SSL implementation for Simple HTTPS from some hard-coded file names -fn ssl() -> Result { - let mut ssl = SslAcceptorBuilder::mozilla_intermediate_raw(SslMethod::tls())?; - - // Server authentication - ssl.set_private_key_file("examples/server-key.pem", X509_FILETYPE_PEM)?; - ssl.set_certificate_chain_file("examples/server-chain.pem")?; - ssl.check_private_key()?; - - Ok(ssl) -} /// Create custom server, wire it to the autogenerated router, /// and pass it to the web server. @@ -56,11 +44,5 @@ fn main() { let addr = "127.0.0.1:80"; - let https = if matches.is_present("https") { - Some(ssl().expect("Failed to load SSL keys")) - } else { - None - }; - - hyper::rt::run(server::create(addr, https)); + hyper::rt::run(server::create(addr, matches.is_present("https"))); } diff --git a/samples/server/petstore/rust-server/output/ops-v3/examples/server/server.rs b/samples/server/petstore/rust-server/output/ops-v3/examples/server/server.rs index 6e464f8b227..701f0c9a0ef 100644 --- a/samples/server/petstore/rust-server/output/ops-v3/examples/server/server.rs +++ b/samples/server/petstore/rust-server/output/ops-v3/examples/server/server.rs @@ -12,7 +12,6 @@ use chrono; use futures::{future, Future, Stream}; use hyper::server::conn::Http; use hyper::service::MakeService as _; -use native_tls; use openssl::ssl::SslAcceptorBuilder; use std::collections::HashMap; use std::marker::PhantomData; @@ -23,12 +22,18 @@ use swagger::{Has, XSpanIdString}; use swagger::auth::MakeAllowAllAuthenticator; use swagger::EmptyContext; use tokio::net::TcpListener; -use tokio_tls::TlsAcceptorExt; +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +use tokio_openssl::SslAcceptorExt; +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod}; + use ops_v3::models; -pub fn create(addr: &str, https: Option) -> Box + Send> { +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +/// Builds an SSL implementation for Simple HTTPS from some hard-coded file names +pub fn create(addr: &str, https: bool) -> Box + Send> { let addr = addr.parse().expect("Failed to parse bind address"); let server = Server::new(); @@ -42,30 +47,44 @@ pub fn create(addr: &str, https: Option) -> Box /// /// Intended for use with custom implementations of connect for e.g. protocol logging /// or similar functionality which requires wrapping the transport layer. When wrapping a TCP connection, - /// this function should be used in conjunction with - /// `swagger::{http_connector, https_connector, https_mutual_connector}`. + /// this function should be used in conjunction with `swagger::Connector::builder()`. /// /// For ordinary tcp connections, prefer the use of `try_new_http`, `try_new_https` /// and `try_new_https_mutual`, to avoid introducing a dependency on the underlying transport layer. @@ -138,18 +136,16 @@ impl Client /// /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" /// * `protocol` - Which protocol to use when constructing the request url, e.g. `Some("http")` - /// * `connector_fn` - Function which returns an implementation of `hyper::client::Connect` + /// * `connector` - Implementation of `hyper::client::Connect` to use for the client pub fn try_new_with_connector( base_path: &str, protocol: Option<&'static str>, - connector_fn: Box C + Send + Sync>, + connector: C, ) -> Result where C: hyper::client::connect::Connect + 'static, C::Transport: 'static, C::Future: 'static, { - let connector = connector_fn(); - let client_service = Box::new(hyper::client::Client::builder().build(connector)); Ok(Client { @@ -165,24 +161,42 @@ impl Client pub fn try_new_http( base_path: &str, ) -> Result { - let http_connector = connector::http_connector(); + let http_connector = Connector::builder().build(); Self::try_new_with_connector(base_path, Some("http"), http_connector) } - /// Create a client with a TLS connection to the server. + /// Create a client with a TLS connection to the server + /// + /// # Arguments + /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" + pub fn try_new_https(base_path: &str) -> Result + { + let https_connector = Connector::builder() + .https() + .build() + .map_err(|e| ClientInitError::SslError(e))?; + Self::try_new_with_connector(base_path, Some("https"), https_connector) + } + + /// Create a client with a TLS connection to the server using a pinned certificate /// /// # Arguments /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" /// * `ca_certificate` - Path to CA certificate used to authenticate the server - pub fn try_new_https( + #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] + pub fn try_new_https_pinned( base_path: &str, ca_certificate: CA, ) -> Result where CA: AsRef, { - let https_connector = connector::https_connector(ca_certificate); + let https_connector = Connector::builder() + .https() + .pin_server_certificate(ca_certificate) + .build() + .map_err(|e| ClientInitError::SslError(e))?; Self::try_new_with_connector(base_path, Some("https"), https_connector) } @@ -193,6 +207,7 @@ impl Client /// * `ca_certificate` - Path to CA certificate used to authenticate the server /// * `client_key` - Path to the client private key /// * `client_certificate` - Path to the client's public certificate associated with the private key + #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] pub fn try_new_https_mutual( base_path: &str, ca_certificate: CA, @@ -204,8 +219,12 @@ impl Client K: AsRef, D: AsRef, { - let https_connector = - connector::https_mutual_connector(ca_certificate, client_key, client_certificate); + let https_connector = Connector::builder() + .https() + .pin_server_certificate(ca_certificate) + .client_authentication(client_key, client_certificate) + .build() + .map_err(|e| ClientInitError::SslError(e))?; Self::try_new_with_connector(base_path, Some("https"), https_connector) } } @@ -239,7 +258,12 @@ pub enum ClientInitError { MissingHost, /// SSL Connection Error - SslError(openssl::error::ErrorStack) + #[cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))] + SslError(native_tls::Error), + + /// SSL Connection Error + #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] + SslError(openssl::error::ErrorStack), } impl From for ClientInitError { @@ -248,12 +272,6 @@ impl From for ClientInitError { } } -impl From for ClientInitError { - fn from(err: openssl::error::ErrorStack) -> ClientInitError { - ClientInitError::SslError(err) - } -} - impl fmt::Display for ClientInitError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let s: &dyn fmt::Debug = self; diff --git a/samples/server/petstore/rust-server/output/ops-v3/src/lib.rs b/samples/server/petstore/rust-server/output/ops-v3/src/lib.rs index e72fdf5f656..4d6fa2c4a3d 100644 --- a/samples/server/petstore/rust-server/output/ops-v3/src/lib.rs +++ b/samples/server/petstore/rust-server/output/ops-v3/src/lib.rs @@ -31,12 +31,9 @@ extern crate swagger; #[cfg(any(feature = "client", feature = "server"))] extern crate hyper; -#[cfg(feature = "client")] -extern crate hyper_tls; -#[cfg(any(feature = "client", feature = "server"))] -extern crate openssl; -#[cfg(any(feature = "client", feature = "server"))] -extern crate native_tls; +#[cfg(feature = "server")] +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +extern crate hyper_openssl; #[cfg(feature = "server")] extern crate percent_encoding; #[cfg(any(feature = "client", feature = "server"))] diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/Cargo.toml b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/Cargo.toml index d523a416138..fd26854d510 100644 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/Cargo.toml +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/Cargo.toml @@ -11,20 +11,27 @@ client = [ "mime_0_2", "multipart", "multipart/client", "swagger/multipart", "serde_urlencoded", - "serde_json", "serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio", "url" + "serde_json", "serde_ignored", "hyper", "hyper-openssl", "native-tls", "openssl", "tokio", "url" ] server = [ "mime_0_2", "multipart", "multipart/server", - "serde_json", "serde_ignored", "hyper", "native-tls", "openssl", "tokio", "tokio-tls", "regex", "percent-encoding", "url", "lazy_static" + "serde_json", "serde_ignored", "hyper", "tokio", "regex", "percent-encoding", "url", "lazy_static" ] conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk-enum-derive"] +[target.'cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))'.dependencies] +native-tls = { version = "0.2", optional = true } + +[target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dependencies] +hyper-openssl = { version = "0.7.1", optional = true } +openssl = {version = "0.10", optional = true } + [dependencies] # Common chrono = { version = "0.4", features = ["serde"] } futures = "0.1" -swagger = "3.0" +swagger = "4.0" log = "0.3.0" mime = "0.3" @@ -41,9 +48,6 @@ uuid = {version = "0.7", features = ["serde", "v4"]} # Common between server and client features hyper = {version = "0.12", optional = true} -hyper-tls = {version = "0.2.1", optional = true} -native-tls = {version = "0.1.4", optional = true} -openssl = {version = "0.9.14", optional = true} serde_json = {version = "1.0", optional = true} serde_ignored = {version = "0.0.4", optional = true} tokio = {version = "0.1.17", optional = true} @@ -56,7 +60,6 @@ serde_urlencoded = {version = "0.5.1", optional = true} lazy_static = { version = "1.4", optional = true } percent-encoding = {version = "1.0.0", optional = true} regex = {version = "0.2", optional = true} -tokio-tls = {version = "0.1.3", optional = true} # Conversion frunk = { version = "0.3.0", optional = true } @@ -70,6 +73,10 @@ clap = "2.25" error-chain = "0.12" env_logger = "0.6" +[target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dev-dependencies] +tokio-openssl = "0.3" +openssl = "0.10" + [[example]] name = "client" required-features = ["client"] diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/client/main.rs b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/client/main.rs index 2ea1346bb60..98c50ff8974 100644 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/client/main.rs +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/client/main.rs @@ -111,9 +111,7 @@ fn main() { let client = if matches.is_present("https") { // Using Simple HTTPS - Client::try_new_https( - &base_url, - "examples/ca.pem") + Client::try_new_https(&base_url) .expect("Failed to create HTTPS client") } else { // Using HTTP diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/server/main.rs b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/server/main.rs index 3d32876acd2..02befef99ba 100644 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/server/main.rs +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/server/main.rs @@ -10,7 +10,6 @@ extern crate env_logger; extern crate hyper; #[macro_use] extern crate log; -extern crate openssl; extern crate swagger; // Imports required by server library. @@ -19,30 +18,19 @@ extern crate chrono; #[macro_use] extern crate error_chain; extern crate futures; -extern crate native_tls; // extern crate swagger; extern crate tokio; -extern crate tokio_tls; extern crate uuid; +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +extern crate openssl; +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +extern crate tokio_openssl; + use clap::{App, Arg}; -use openssl::x509::X509_FILETYPE_PEM; -use openssl::ssl::{SslAcceptorBuilder, SslMethod}; -use openssl::error::ErrorStack; mod server; -// Builds an SSL implementation for Simple HTTPS from some hard-coded file names -fn ssl() -> Result { - let mut ssl = SslAcceptorBuilder::mozilla_intermediate_raw(SslMethod::tls())?; - - // Server authentication - ssl.set_private_key_file("examples/server-key.pem", X509_FILETYPE_PEM)?; - ssl.set_certificate_chain_file("examples/server-chain.pem")?; - ssl.check_private_key()?; - - Ok(ssl) -} /// Create custom server, wire it to the autogenerated router, /// and pass it to the web server. @@ -57,11 +45,5 @@ fn main() { let addr = "127.0.0.1:80"; - let https = if matches.is_present("https") { - Some(ssl().expect("Failed to load SSL keys")) - } else { - None - }; - - hyper::rt::run(server::create(addr, https)); + hyper::rt::run(server::create(addr, matches.is_present("https"))); } diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/server/server.rs b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/server/server.rs index b99fd9af2b3..bf7a7a7bfe7 100644 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/server/server.rs +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/examples/server/server.rs @@ -12,7 +12,6 @@ use chrono; use futures::{future, Future, Stream}; use hyper::server::conn::Http; use hyper::service::MakeService as _; -use native_tls; use openssl::ssl::SslAcceptorBuilder; use std::collections::HashMap; use std::marker::PhantomData; @@ -23,12 +22,18 @@ use swagger::{Has, XSpanIdString}; use swagger::auth::MakeAllowAllAuthenticator; use swagger::EmptyContext; use tokio::net::TcpListener; -use tokio_tls::TlsAcceptorExt; use uuid; +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +use tokio_openssl::SslAcceptorExt; +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod}; + use petstore_with_fake_endpoints_models_for_testing::models; -pub fn create(addr: &str, https: Option) -> Box + Send> { +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +/// Builds an SSL implementation for Simple HTTPS from some hard-coded file names +pub fn create(addr: &str, https: bool) -> Box + Send> { let addr = addr.parse().expect("Failed to parse bind address"); let server = Server::new(); @@ -42,30 +47,44 @@ pub fn create(addr: &str, https: Option) -> Box /// /// Intended for use with custom implementations of connect for e.g. protocol logging /// or similar functionality which requires wrapping the transport layer. When wrapping a TCP connection, - /// this function should be used in conjunction with - /// `swagger::{http_connector, https_connector, https_mutual_connector}`. + /// this function should be used in conjunction with `swagger::Connector::builder()`. /// /// For ordinary tcp connections, prefer the use of `try_new_http`, `try_new_https` /// and `try_new_https_mutual`, to avoid introducing a dependency on the underlying transport layer. @@ -141,18 +139,16 @@ impl Client /// /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" /// * `protocol` - Which protocol to use when constructing the request url, e.g. `Some("http")` - /// * `connector_fn` - Function which returns an implementation of `hyper::client::Connect` + /// * `connector` - Implementation of `hyper::client::Connect` to use for the client pub fn try_new_with_connector( base_path: &str, protocol: Option<&'static str>, - connector_fn: Box C + Send + Sync>, + connector: C, ) -> Result where C: hyper::client::connect::Connect + 'static, C::Transport: 'static, C::Future: 'static, { - let connector = connector_fn(); - let client_service = Box::new(hyper::client::Client::builder().build(connector)); Ok(Client { @@ -168,24 +164,42 @@ impl Client pub fn try_new_http( base_path: &str, ) -> Result { - let http_connector = connector::http_connector(); + let http_connector = Connector::builder().build(); Self::try_new_with_connector(base_path, Some("http"), http_connector) } - /// Create a client with a TLS connection to the server. + /// Create a client with a TLS connection to the server + /// + /// # Arguments + /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" + pub fn try_new_https(base_path: &str) -> Result + { + let https_connector = Connector::builder() + .https() + .build() + .map_err(|e| ClientInitError::SslError(e))?; + Self::try_new_with_connector(base_path, Some("https"), https_connector) + } + + /// Create a client with a TLS connection to the server using a pinned certificate /// /// # Arguments /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" /// * `ca_certificate` - Path to CA certificate used to authenticate the server - pub fn try_new_https( + #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] + pub fn try_new_https_pinned( base_path: &str, ca_certificate: CA, ) -> Result where CA: AsRef, { - let https_connector = connector::https_connector(ca_certificate); + let https_connector = Connector::builder() + .https() + .pin_server_certificate(ca_certificate) + .build() + .map_err(|e| ClientInitError::SslError(e))?; Self::try_new_with_connector(base_path, Some("https"), https_connector) } @@ -196,6 +210,7 @@ impl Client /// * `ca_certificate` - Path to CA certificate used to authenticate the server /// * `client_key` - Path to the client private key /// * `client_certificate` - Path to the client's public certificate associated with the private key + #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] pub fn try_new_https_mutual( base_path: &str, ca_certificate: CA, @@ -207,8 +222,12 @@ impl Client K: AsRef, D: AsRef, { - let https_connector = - connector::https_mutual_connector(ca_certificate, client_key, client_certificate); + let https_connector = Connector::builder() + .https() + .pin_server_certificate(ca_certificate) + .client_authentication(client_key, client_certificate) + .build() + .map_err(|e| ClientInitError::SslError(e))?; Self::try_new_with_connector(base_path, Some("https"), https_connector) } } @@ -242,7 +261,12 @@ pub enum ClientInitError { MissingHost, /// SSL Connection Error - SslError(openssl::error::ErrorStack) + #[cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))] + SslError(native_tls::Error), + + /// SSL Connection Error + #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] + SslError(openssl::error::ErrorStack), } impl From for ClientInitError { @@ -251,12 +275,6 @@ impl From for ClientInitError { } } -impl From for ClientInitError { - fn from(err: openssl::error::ErrorStack) -> ClientInitError { - ClientInitError::SslError(err) - } -} - impl fmt::Display for ClientInitError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let s: &dyn fmt::Debug = self; diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/lib.rs b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/lib.rs index 815b16e8622..004b9babcf6 100644 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/lib.rs +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/lib.rs @@ -31,14 +31,11 @@ extern crate swagger; #[cfg(any(feature = "client", feature = "server"))] extern crate hyper; -#[cfg(feature = "client")] -extern crate hyper_tls; -#[cfg(any(feature = "client", feature = "server"))] -extern crate openssl; +#[cfg(feature = "server")] +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +extern crate hyper_openssl; #[cfg(any(feature = "client", feature = "server"))] extern crate mime_0_2; -#[cfg(any(feature = "client", feature = "server"))] -extern crate native_tls; #[cfg(feature = "server")] extern crate percent_encoding; #[cfg(any(feature = "client", feature = "server"))] diff --git a/samples/server/petstore/rust-server/output/rust-server-test/Cargo.toml b/samples/server/petstore/rust-server/output/rust-server-test/Cargo.toml index 0caf2ce6e2a..917a91bffb6 100644 --- a/samples/server/petstore/rust-server/output/rust-server-test/Cargo.toml +++ b/samples/server/petstore/rust-server/output/rust-server-test/Cargo.toml @@ -8,18 +8,25 @@ license = "Unlicense" [features] default = ["client", "server"] client = [ - "serde_json", "serde_ignored", "hyper", "hyper-tls", "native-tls", "openssl", "tokio", "url" + "serde_json", "serde_ignored", "hyper", "hyper-openssl", "native-tls", "openssl", "tokio", "url" ] server = [ - "serde_json", "serde_ignored", "hyper", "native-tls", "openssl", "tokio", "tokio-tls", "regex", "percent-encoding", "url", "lazy_static" + "serde_json", "serde_ignored", "hyper", "tokio", "regex", "percent-encoding", "url", "lazy_static" ] conversion = ["frunk", "frunk_derives", "frunk_core", "frunk-enum-core", "frunk-enum-derive"] +[target.'cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))'.dependencies] +native-tls = { version = "0.2", optional = true } + +[target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dependencies] +hyper-openssl = { version = "0.7.1", optional = true } +openssl = {version = "0.10", optional = true } + [dependencies] # Common chrono = { version = "0.4", features = ["serde"] } futures = "0.1" -swagger = "3.0" +swagger = "4.0" log = "0.3.0" mime = "0.3" @@ -30,9 +37,6 @@ serde_derive = "1.0" # Common between server and client features hyper = {version = "0.12", optional = true} -hyper-tls = {version = "0.2.1", optional = true} -native-tls = {version = "0.1.4", optional = true} -openssl = {version = "0.9.14", optional = true} serde_json = {version = "1.0", optional = true} serde_ignored = {version = "0.0.4", optional = true} tokio = {version = "0.1.17", optional = true} @@ -44,7 +48,6 @@ url = {version = "1.5", optional = true} lazy_static = { version = "1.4", optional = true } percent-encoding = {version = "1.0.0", optional = true} regex = {version = "0.2", optional = true} -tokio-tls = {version = "0.1.3", optional = true} # Conversion frunk = { version = "0.3.0", optional = true } @@ -59,6 +62,10 @@ error-chain = "0.12" env_logger = "0.6" uuid = {version = "0.7", features = ["serde", "v4"]} +[target.'cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))'.dev-dependencies] +tokio-openssl = "0.3" +openssl = "0.10" + [[example]] name = "client" required-features = ["client"] diff --git a/samples/server/petstore/rust-server/output/rust-server-test/examples/client/main.rs b/samples/server/petstore/rust-server/output/rust-server-test/examples/client/main.rs index 733f7f69e6d..9ef34cb7096 100644 --- a/samples/server/petstore/rust-server/output/rust-server-test/examples/client/main.rs +++ b/samples/server/petstore/rust-server/output/rust-server-test/examples/client/main.rs @@ -67,9 +67,7 @@ fn main() { let client = if matches.is_present("https") { // Using Simple HTTPS - Client::try_new_https( - &base_url, - "examples/ca.pem") + Client::try_new_https(&base_url) .expect("Failed to create HTTPS client") } else { // Using HTTP diff --git a/samples/server/petstore/rust-server/output/rust-server-test/examples/server/main.rs b/samples/server/petstore/rust-server/output/rust-server-test/examples/server/main.rs index 5c444ab2d94..7243ef6cbb0 100644 --- a/samples/server/petstore/rust-server/output/rust-server-test/examples/server/main.rs +++ b/samples/server/petstore/rust-server/output/rust-server-test/examples/server/main.rs @@ -10,7 +10,6 @@ extern crate env_logger; extern crate hyper; #[macro_use] extern crate log; -extern crate openssl; extern crate swagger; // Imports required by server library. @@ -19,29 +18,18 @@ extern crate chrono; #[macro_use] extern crate error_chain; extern crate futures; -extern crate native_tls; // extern crate swagger; extern crate tokio; -extern crate tokio_tls; + +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +extern crate openssl; +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +extern crate tokio_openssl; use clap::{App, Arg}; -use openssl::x509::X509_FILETYPE_PEM; -use openssl::ssl::{SslAcceptorBuilder, SslMethod}; -use openssl::error::ErrorStack; mod server; -// Builds an SSL implementation for Simple HTTPS from some hard-coded file names -fn ssl() -> Result { - let mut ssl = SslAcceptorBuilder::mozilla_intermediate_raw(SslMethod::tls())?; - - // Server authentication - ssl.set_private_key_file("examples/server-key.pem", X509_FILETYPE_PEM)?; - ssl.set_certificate_chain_file("examples/server-chain.pem")?; - ssl.check_private_key()?; - - Ok(ssl) -} /// Create custom server, wire it to the autogenerated router, /// and pass it to the web server. @@ -56,11 +44,5 @@ fn main() { let addr = "127.0.0.1:80"; - let https = if matches.is_present("https") { - Some(ssl().expect("Failed to load SSL keys")) - } else { - None - }; - - hyper::rt::run(server::create(addr, https)); + hyper::rt::run(server::create(addr, matches.is_present("https"))); } diff --git a/samples/server/petstore/rust-server/output/rust-server-test/examples/server/server.rs b/samples/server/petstore/rust-server/output/rust-server-test/examples/server/server.rs index 1f359b72f9f..f7a1796d28b 100644 --- a/samples/server/petstore/rust-server/output/rust-server-test/examples/server/server.rs +++ b/samples/server/petstore/rust-server/output/rust-server-test/examples/server/server.rs @@ -12,7 +12,6 @@ use chrono; use futures::{future, Future, Stream}; use hyper::server::conn::Http; use hyper::service::MakeService as _; -use native_tls; use openssl::ssl::SslAcceptorBuilder; use std::collections::HashMap; use std::marker::PhantomData; @@ -23,12 +22,18 @@ use swagger::{Has, XSpanIdString}; use swagger::auth::MakeAllowAllAuthenticator; use swagger::EmptyContext; use tokio::net::TcpListener; -use tokio_tls::TlsAcceptorExt; +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +use tokio_openssl::SslAcceptorExt; +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod}; + use rust_server_test::models; -pub fn create(addr: &str, https: Option) -> Box + Send> { +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +/// Builds an SSL implementation for Simple HTTPS from some hard-coded file names +pub fn create(addr: &str, https: bool) -> Box + Send> { let addr = addr.parse().expect("Failed to parse bind address"); let server = Server::new(); @@ -42,30 +47,44 @@ pub fn create(addr: &str, https: Option) -> Box /// /// Intended for use with custom implementations of connect for e.g. protocol logging /// or similar functionality which requires wrapping the transport layer. When wrapping a TCP connection, - /// this function should be used in conjunction with - /// `swagger::{http_connector, https_connector, https_mutual_connector}`. + /// this function should be used in conjunction with `swagger::Connector::builder()`. /// /// For ordinary tcp connections, prefer the use of `try_new_http`, `try_new_https` /// and `try_new_https_mutual`, to avoid introducing a dependency on the underlying transport layer. @@ -110,18 +108,16 @@ impl Client /// /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" /// * `protocol` - Which protocol to use when constructing the request url, e.g. `Some("http")` - /// * `connector_fn` - Function which returns an implementation of `hyper::client::Connect` + /// * `connector` - Implementation of `hyper::client::Connect` to use for the client pub fn try_new_with_connector( base_path: &str, protocol: Option<&'static str>, - connector_fn: Box C + Send + Sync>, + connector: C, ) -> Result where C: hyper::client::connect::Connect + 'static, C::Transport: 'static, C::Future: 'static, { - let connector = connector_fn(); - let client_service = Box::new(hyper::client::Client::builder().build(connector)); Ok(Client { @@ -137,24 +133,42 @@ impl Client pub fn try_new_http( base_path: &str, ) -> Result { - let http_connector = connector::http_connector(); + let http_connector = Connector::builder().build(); Self::try_new_with_connector(base_path, Some("http"), http_connector) } - /// Create a client with a TLS connection to the server. + /// Create a client with a TLS connection to the server + /// + /// # Arguments + /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" + pub fn try_new_https(base_path: &str) -> Result + { + let https_connector = Connector::builder() + .https() + .build() + .map_err(|e| ClientInitError::SslError(e))?; + Self::try_new_with_connector(base_path, Some("https"), https_connector) + } + + /// Create a client with a TLS connection to the server using a pinned certificate /// /// # Arguments /// * `base_path` - base path of the client API, i.e. "www.my-api-implementation.com" /// * `ca_certificate` - Path to CA certificate used to authenticate the server - pub fn try_new_https( + #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] + pub fn try_new_https_pinned( base_path: &str, ca_certificate: CA, ) -> Result where CA: AsRef, { - let https_connector = connector::https_connector(ca_certificate); + let https_connector = Connector::builder() + .https() + .pin_server_certificate(ca_certificate) + .build() + .map_err(|e| ClientInitError::SslError(e))?; Self::try_new_with_connector(base_path, Some("https"), https_connector) } @@ -165,6 +179,7 @@ impl Client /// * `ca_certificate` - Path to CA certificate used to authenticate the server /// * `client_key` - Path to the client private key /// * `client_certificate` - Path to the client's public certificate associated with the private key + #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] pub fn try_new_https_mutual( base_path: &str, ca_certificate: CA, @@ -176,8 +191,12 @@ impl Client K: AsRef, D: AsRef, { - let https_connector = - connector::https_mutual_connector(ca_certificate, client_key, client_certificate); + let https_connector = Connector::builder() + .https() + .pin_server_certificate(ca_certificate) + .client_authentication(client_key, client_certificate) + .build() + .map_err(|e| ClientInitError::SslError(e))?; Self::try_new_with_connector(base_path, Some("https"), https_connector) } } @@ -211,7 +230,12 @@ pub enum ClientInitError { MissingHost, /// SSL Connection Error - SslError(openssl::error::ErrorStack) + #[cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))] + SslError(native_tls::Error), + + /// SSL Connection Error + #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] + SslError(openssl::error::ErrorStack), } impl From for ClientInitError { @@ -220,12 +244,6 @@ impl From for ClientInitError { } } -impl From for ClientInitError { - fn from(err: openssl::error::ErrorStack) -> ClientInitError { - ClientInitError::SslError(err) - } -} - impl fmt::Display for ClientInitError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let s: &dyn fmt::Debug = self; diff --git a/samples/server/petstore/rust-server/output/rust-server-test/src/lib.rs b/samples/server/petstore/rust-server/output/rust-server-test/src/lib.rs index 0db8e0dd1f0..0c6e36818c7 100644 --- a/samples/server/petstore/rust-server/output/rust-server-test/src/lib.rs +++ b/samples/server/petstore/rust-server/output/rust-server-test/src/lib.rs @@ -31,12 +31,9 @@ extern crate swagger; #[cfg(any(feature = "client", feature = "server"))] extern crate hyper; -#[cfg(feature = "client")] -extern crate hyper_tls; -#[cfg(any(feature = "client", feature = "server"))] -extern crate openssl; -#[cfg(any(feature = "client", feature = "server"))] -extern crate native_tls; +#[cfg(feature = "server")] +#[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] +extern crate hyper_openssl; #[cfg(feature = "server")] extern crate percent_encoding; #[cfg(any(feature = "client", feature = "server"))]