How to create an optional ssl server?
kpp opened this issue · comments
I want to create either a secure serve or insecure based on --args
passed to my application.
Let's say I got:
use tokio::reactor::Handle as ReactorHandle;
use websocket::r#async::Server;
use structopt::StructOpt;
#[derive(StructOpt, Debug)]
struct Opt {
// ...
}
fn main() {
let opt = Opt::from_args();
let server = if opt.insecure {
let srv = Server::bind("127.0.0.1:2794", &ReactorHandle::default()).unwrap();
Box::new(srv) as Box<Server<_>>
} else {
let mut file = std::fs::File::open(opt.pfx_path.unwrap()).expect("Could not find pfx file");
let mut pkcs12 = vec![];
file.read_to_end(&mut pkcs12).expect("Could not read pfx file");
let pkcs12 = native_tls::Identity::from_pkcs12(&pkcs12, &opt.pfx_pass.unwrap())
.expect("Could not create pkcs12");
let acceptor = native_tls::TlsAcceptor::builder(pkcs12).build()
.expect("Could not create TlsAcceptor");
let srv = Server::bind_secure("127.0.0.1:2794", acceptor, &ReactorHandle::default()).unwrap();
Box::new(srv) as Box<Server<_>>
};
let f = server
.incoming()
//...
let mut runtime = tokio::runtime::Builder::new().build().unwrap();
runtime.block_on(f).unwrap();
}
However I got this error:
error[E0034]: multiple applicable items in scope
--> src/main.rs:96:10
|
96 | .incoming()
| ^^^^^^^^ multiple `incoming` found
|
= note: candidate #1 is defined in an impl for the type `websocket::server::WsServer<websocket::server::NoTlsAcceptor, websocket::async::TcpListener>`
= note: candidate #2 is defined in an impl for the type `websocket::server::WsServer<native_tls::TlsAcceptor, websocket::async::TcpListener>`
error: aborting due to previous error
use websocket::server::{InvalidConnection, OptionalTlsAcceptor, NoTlsAcceptor};
use websocket::server::r#async::{Incoming};
use websocket::r#async::{Server, TcpStream as wsTcpStream, Stream as wsStream};
struct OptionalTlsServer<S: OptionalTlsAcceptor>
{
pub server: Server<S>,
}
trait OptionalTlsServerTrait {
type IncomingStream: Read + Write + wsStream + Send + 'static;
fn incoming(self) -> Incoming<Self::IncomingStream>;
}
impl OptionalTlsServerTrait for OptionalTlsServer<native_tls::TlsAcceptor> {
type IncomingStream = TlsStream<wsTcpStream>;
fn incoming(self) -> Incoming<Self::IncomingStream> {
self.server.incoming()
}
}
impl OptionalTlsServerTrait for OptionalTlsServer<NoTlsAcceptor> {
type IncomingStream = wsTcpStream;
fn incoming(self) -> Incoming<Self::IncomingStream> {
self.server.incoming()
}
}
fn run_server(server: impl OptionalTlsServerTrait) {
server.incoming()....
}
impl OptionalTlsServerTrait
This way the code in run_server
may be duplicated, leading to increased executable size.
Another options should by usabe of trait object, like a dyn OptionalTlsServerTrait
. But fn incoming
should not accept self
without reference then.
leading to increased executable size
I don't care =) I did not want to duplicate my code manually.
Also one important thing: can I use WS but hide it behind nginx https somehow?
Yes.
Uncomment localhost:
instead of unix:
, but if needed rust-websocket
can do over UNIX sockets as well.