mirror of
https://github.com/actix/actix-extras.git
synced 2024-11-23 23:51:06 +01:00
enable ssl feature
This commit is contained in:
parent
7cf9af9b55
commit
6a61138bf8
@ -32,12 +32,12 @@ script:
|
|||||||
- |
|
- |
|
||||||
if [[ "$TRAVIS_RUST_VERSION" != "stable" ]]; then
|
if [[ "$TRAVIS_RUST_VERSION" != "stable" ]]; then
|
||||||
cargo clean
|
cargo clean
|
||||||
cargo test --features="" -- --nocapture
|
cargo test --features="ssl" -- --nocapture
|
||||||
fi
|
fi
|
||||||
- |
|
- |
|
||||||
if [[ "$TRAVIS_RUST_VERSION" == "stable" ]]; then
|
if [[ "$TRAVIS_RUST_VERSION" == "stable" ]]; then
|
||||||
RUSTFLAGS="--cfg procmacro2_semver_exempt" cargo install -f cargo-tarpaulin
|
RUSTFLAGS="--cfg procmacro2_semver_exempt" cargo install -f cargo-tarpaulin
|
||||||
cargo tarpaulin --features="" --out Xml --no-count
|
cargo tarpaulin --features="ssl" --out Xml --no-count
|
||||||
bash <(curl -s https://codecov.io/bash)
|
bash <(curl -s https://codecov.io/bash)
|
||||||
echo "Uploaded code coverage"
|
echo "Uploaded code coverage"
|
||||||
fi
|
fi
|
||||||
@ -46,7 +46,7 @@ script:
|
|||||||
after_success:
|
after_success:
|
||||||
- |
|
- |
|
||||||
if [[ "$TRAVIS_OS_NAME" == "linux" && "$TRAVIS_PULL_REQUEST" = "false" && "$TRAVIS_BRANCH" == "master" && "$TRAVIS_RUST_VERSION" == "beta" ]]; then
|
if [[ "$TRAVIS_OS_NAME" == "linux" && "$TRAVIS_PULL_REQUEST" = "false" && "$TRAVIS_BRANCH" == "master" && "$TRAVIS_RUST_VERSION" == "beta" ]]; then
|
||||||
cargo doc --features "session" --no-deps &&
|
cargo doc --features "ssl,session" --no-deps &&
|
||||||
echo "<meta http-equiv=refresh content=0;url=os_balloon/index.html>" > target/doc/index.html &&
|
echo "<meta http-equiv=refresh content=0;url=os_balloon/index.html>" > target/doc/index.html &&
|
||||||
git clone https://github.com/davisp/ghp-import.git &&
|
git clone https://github.com/davisp/ghp-import.git &&
|
||||||
./ghp-import/ghp_import.py -n -p -f -m "Documentation upload" -r https://"$GH_TOKEN"@github.com/"$TRAVIS_REPO_SLUG.git" target/doc &&
|
./ghp-import/ghp_import.py -n -p -f -m "Documentation upload" -r https://"$GH_TOKEN"@github.com/"$TRAVIS_REPO_SLUG.git" target/doc &&
|
||||||
|
@ -35,6 +35,9 @@ default = ["session", "brotli", "flate2-c"]
|
|||||||
tls = ["native-tls", "tokio-tls"]
|
tls = ["native-tls", "tokio-tls"]
|
||||||
|
|
||||||
# openssl
|
# openssl
|
||||||
|
ssl = ["openssl", "tokio-openssl", "actix-net/ssl"]
|
||||||
|
|
||||||
|
# deprecated, use "ssl"
|
||||||
alpn = ["openssl", "tokio-openssl", "actix-net/ssl"]
|
alpn = ["openssl", "tokio-openssl", "actix-net/ssl"]
|
||||||
|
|
||||||
# rustls
|
# rustls
|
||||||
|
@ -64,8 +64,8 @@
|
|||||||
//! ## Package feature
|
//! ## Package feature
|
||||||
//!
|
//!
|
||||||
//! * `tls` - enables ssl support via `native-tls` crate
|
//! * `tls` - enables ssl support via `native-tls` crate
|
||||||
//! * `alpn` - enables ssl support via `openssl` crate, require for `http/2`
|
//! * `ssl` - enables ssl support via `openssl` crate, supports `http/2`
|
||||||
//! support
|
//! * `rust-tls` - enables ssl support via `rustls` crate, supports `http/2`
|
||||||
//! * `uds` - enables support for making client requests via Unix Domain Sockets.
|
//! * `uds` - enables support for making client requests via Unix Domain Sockets.
|
||||||
//! Unix only. Not necessary for *serving* requests.
|
//! Unix only. Not necessary for *serving* requests.
|
||||||
//! * `session` - enables session support, includes `ring` crate as
|
//! * `session` - enables session support, includes `ring` crate as
|
||||||
|
@ -517,15 +517,14 @@ mod tests {
|
|||||||
use httpmessage::HttpMessage;
|
use httpmessage::HttpMessage;
|
||||||
use server::h1decoder::Message;
|
use server::h1decoder::Message;
|
||||||
use server::settings::{ServerSettings, WorkerSettings};
|
use server::settings::{ServerSettings, WorkerSettings};
|
||||||
use server::{Connections, KeepAlive, Request};
|
use server::{KeepAlive, Request};
|
||||||
|
|
||||||
fn wrk_settings() -> Rc<WorkerSettings<HttpApplication>> {
|
fn wrk_settings() -> WorkerSettings<HttpApplication> {
|
||||||
Rc::new(WorkerSettings::<HttpApplication>::new(
|
WorkerSettings::<HttpApplication>::new(
|
||||||
Vec::new(),
|
Vec::new(),
|
||||||
KeepAlive::Os,
|
KeepAlive::Os,
|
||||||
ServerSettings::default(),
|
ServerSettings::default(),
|
||||||
Connections::default(),
|
)
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Message {
|
impl Message {
|
||||||
@ -644,9 +643,9 @@ mod tests {
|
|||||||
fn test_req_parse1() {
|
fn test_req_parse1() {
|
||||||
let buf = Buffer::new("GET /test HTTP/1.1\r\n\r\n");
|
let buf = Buffer::new("GET /test HTTP/1.1\r\n\r\n");
|
||||||
let readbuf = BytesMut::new();
|
let readbuf = BytesMut::new();
|
||||||
let settings = Rc::new(wrk_settings());
|
let settings = wrk_settings();
|
||||||
|
|
||||||
let mut h1 = Http1::new(Rc::clone(&settings), buf, None, readbuf, false, None);
|
let mut h1 = Http1::new(settings.clone(), buf, None, readbuf, false, None);
|
||||||
h1.poll_io();
|
h1.poll_io();
|
||||||
h1.poll_io();
|
h1.poll_io();
|
||||||
assert_eq!(h1.tasks.len(), 1);
|
assert_eq!(h1.tasks.len(), 1);
|
||||||
@ -657,9 +656,9 @@ mod tests {
|
|||||||
let buf = Buffer::new("");
|
let buf = Buffer::new("");
|
||||||
let readbuf =
|
let readbuf =
|
||||||
BytesMut::from(Vec::<u8>::from(&b"GET /test HTTP/1.1\r\n\r\n"[..]));
|
BytesMut::from(Vec::<u8>::from(&b"GET /test HTTP/1.1\r\n\r\n"[..]));
|
||||||
let settings = Rc::new(wrk_settings());
|
let settings = wrk_settings();
|
||||||
|
|
||||||
let mut h1 = Http1::new(Rc::clone(&settings), buf, None, readbuf, true, None);
|
let mut h1 = Http1::new(settings.clone(), buf, None, readbuf, true, None);
|
||||||
h1.poll_io();
|
h1.poll_io();
|
||||||
assert_eq!(h1.tasks.len(), 1);
|
assert_eq!(h1.tasks.len(), 1);
|
||||||
}
|
}
|
||||||
@ -668,9 +667,9 @@ mod tests {
|
|||||||
fn test_req_parse_err() {
|
fn test_req_parse_err() {
|
||||||
let buf = Buffer::new("GET /test HTTP/1\r\n\r\n");
|
let buf = Buffer::new("GET /test HTTP/1\r\n\r\n");
|
||||||
let readbuf = BytesMut::new();
|
let readbuf = BytesMut::new();
|
||||||
let settings = Rc::new(wrk_settings());
|
let settings = wrk_settings();
|
||||||
|
|
||||||
let mut h1 = Http1::new(Rc::clone(&settings), buf, None, readbuf, false, None);
|
let mut h1 = Http1::new(settings.clone(), buf, None, readbuf, false, None);
|
||||||
h1.poll_io();
|
h1.poll_io();
|
||||||
h1.poll_io();
|
h1.poll_io();
|
||||||
assert!(h1.flags.contains(Flags::ERROR));
|
assert!(h1.flags.contains(Flags::ERROR));
|
||||||
|
@ -2,19 +2,19 @@ use std::marker::PhantomData;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::{io, mem, net, time};
|
use std::{io, mem, net, time};
|
||||||
|
|
||||||
use actix::{Actor, Addr, Arbiter, AsyncContext, Context, Handler, System};
|
use actix::{Actor, Addr, AsyncContext, Context, Handler, System};
|
||||||
|
use actix_net::{ssl, NewService, NewServiceExt, Server, Service};
|
||||||
|
|
||||||
use futures::future::{ok, FutureResult};
|
use futures::future::{ok, FutureResult};
|
||||||
use futures::{Async, Poll, Stream};
|
use futures::{Async, Poll, Stream};
|
||||||
use net2::TcpBuilder;
|
use net2::TcpBuilder;
|
||||||
use num_cpus;
|
use num_cpus;
|
||||||
|
use tokio_tcp::TcpStream;
|
||||||
use actix_net::{ssl, NewService, Server, Service};
|
|
||||||
|
|
||||||
//#[cfg(feature = "tls")]
|
//#[cfg(feature = "tls")]
|
||||||
//use native_tls::TlsAcceptor;
|
//use native_tls::TlsAcceptor;
|
||||||
|
|
||||||
#[cfg(feature = "alpn")]
|
#[cfg(any(feature = "alpn", feature = "ssl"))]
|
||||||
use openssl::ssl::SslAcceptorBuilder;
|
use openssl::ssl::SslAcceptorBuilder;
|
||||||
|
|
||||||
//#[cfg(feature = "rust-tls")]
|
//#[cfg(feature = "rust-tls")]
|
||||||
@ -25,9 +25,10 @@ use super::settings::{ServerSettings, WorkerSettings};
|
|||||||
use super::{HttpHandler, IntoHttpHandler, IoStream, KeepAlive};
|
use super::{HttpHandler, IntoHttpHandler, IoStream, KeepAlive};
|
||||||
|
|
||||||
struct Socket<H: IntoHttpHandler> {
|
struct Socket<H: IntoHttpHandler> {
|
||||||
|
scheme: &'static str,
|
||||||
lst: net::TcpListener,
|
lst: net::TcpListener,
|
||||||
addr: net::SocketAddr,
|
addr: net::SocketAddr,
|
||||||
handler: Box<IoStreamHandler<H>>,
|
handler: Box<ServiceFactory<H>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An HTTP Server
|
/// An HTTP Server
|
||||||
@ -194,10 +195,7 @@ where
|
|||||||
/// and the user should be presented with an enumeration of which
|
/// and the user should be presented with an enumeration of which
|
||||||
/// socket requires which protocol.
|
/// socket requires which protocol.
|
||||||
pub fn addrs_with_scheme(&self) -> Vec<(net::SocketAddr, &str)> {
|
pub fn addrs_with_scheme(&self) -> Vec<(net::SocketAddr, &str)> {
|
||||||
self.sockets
|
self.sockets.iter().map(|s| (s.addr, s.scheme)).collect()
|
||||||
.iter()
|
|
||||||
.map(|s| (s.addr, s.handler.scheme()))
|
|
||||||
.collect()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Use listener for accepting incoming connection requests
|
/// Use listener for accepting incoming connection requests
|
||||||
@ -209,7 +207,8 @@ where
|
|||||||
self.sockets.push(Socket {
|
self.sockets.push(Socket {
|
||||||
lst,
|
lst,
|
||||||
addr,
|
addr,
|
||||||
handler: Box::new(SimpleHandler {
|
scheme: "http",
|
||||||
|
handler: Box::new(SimpleFactory {
|
||||||
addr,
|
addr,
|
||||||
factory: self.factory.clone(),
|
factory: self.factory.clone(),
|
||||||
}),
|
}),
|
||||||
@ -218,22 +217,28 @@ where
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
// #[doc(hidden)]
|
#[doc(hidden)]
|
||||||
// /// Use listener for accepting incoming connection requests
|
/// Use listener for accepting incoming connection requests
|
||||||
// pub fn listen_with<A>(mut self, lst: net::TcpListener, acceptor: A) -> Self
|
pub(crate) fn listen_with<T, F>(mut self, lst: net::TcpListener, acceptor: F) -> Self
|
||||||
// where
|
where
|
||||||
// A: AcceptorService<TcpStream> + Send + 'static,
|
F: Fn() -> T + Send + Clone + 'static,
|
||||||
// {
|
T: NewService<Request = TcpStream, Error = (), InitError = ()> + Clone + 'static,
|
||||||
// let token = Token(self.handlers.len());
|
T::Response: IoStream,
|
||||||
// let addr = lst.local_addr().unwrap();
|
{
|
||||||
// self.handlers.push(Box::new(StreamHandler::new(
|
let addr = lst.local_addr().unwrap();
|
||||||
// lst.local_addr().unwrap(),
|
self.sockets.push(Socket {
|
||||||
// acceptor,
|
lst,
|
||||||
// )));
|
addr,
|
||||||
// self.sockets.push(Socket { lst, addr, token });
|
scheme: "https",
|
||||||
|
handler: Box::new(AcceptorFactory {
|
||||||
|
addr,
|
||||||
|
acceptor,
|
||||||
|
factory: self.factory.clone(),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
// self
|
self
|
||||||
// }
|
}
|
||||||
|
|
||||||
// #[cfg(feature = "tls")]
|
// #[cfg(feature = "tls")]
|
||||||
// /// Use listener for accepting incoming tls connection requests
|
// /// Use listener for accepting incoming tls connection requests
|
||||||
@ -246,24 +251,27 @@ where
|
|||||||
// self.listen_with(lst, NativeTlsAcceptor::new(acceptor))
|
// self.listen_with(lst, NativeTlsAcceptor::new(acceptor))
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// #[cfg(feature = "alpn")]
|
#[cfg(any(feature = "alpn", feature = "ssl"))]
|
||||||
// /// Use listener for accepting incoming tls connection requests
|
/// Use listener for accepting incoming tls connection requests
|
||||||
// ///
|
///
|
||||||
// /// This method sets alpn protocols to "h2" and "http/1.1"
|
/// This method sets alpn protocols to "h2" and "http/1.1"
|
||||||
// pub fn listen_ssl(
|
pub fn listen_ssl(
|
||||||
// self, lst: net::TcpListener, builder: SslAcceptorBuilder,
|
self, lst: net::TcpListener, builder: SslAcceptorBuilder,
|
||||||
// ) -> io::Result<Self> {
|
) -> io::Result<Self> {
|
||||||
// use super::{OpensslAcceptor, ServerFlags};
|
use super::{openssl_acceptor_with_flags, ServerFlags};
|
||||||
|
|
||||||
// alpn support
|
let flags = if self.no_http2 {
|
||||||
// let flags = if self.no_http2 {
|
ServerFlags::HTTP1
|
||||||
// ServerFlags::HTTP1
|
} else {
|
||||||
// } else {
|
ServerFlags::HTTP1 | ServerFlags::HTTP2
|
||||||
// ServerFlags::HTTP1 | ServerFlags::HTTP2
|
};
|
||||||
// };
|
|
||||||
|
|
||||||
// Ok(self.listen_with(lst, OpensslAcceptor::with_flags(builder, flags)?))
|
let acceptor = openssl_acceptor_with_flags(builder, flags)?;
|
||||||
// }
|
|
||||||
|
Ok(self.listen_with(lst, move || {
|
||||||
|
ssl::OpensslAcceptor::new(acceptor.clone()).map_err(|_| ())
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
// #[cfg(feature = "rust-tls")]
|
// #[cfg(feature = "rust-tls")]
|
||||||
// /// Use listener for accepting incoming tls connection requests
|
// /// Use listener for accepting incoming tls connection requests
|
||||||
@ -400,60 +408,6 @@ where
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
struct HttpService<H, F, Io>
|
|
||||||
where
|
|
||||||
H: HttpHandler,
|
|
||||||
F: IntoHttpHandler<Handler = H>,
|
|
||||||
Io: IoStream,
|
|
||||||
{
|
|
||||||
factory: Arc<Fn() -> Vec<F> + Send + Sync>,
|
|
||||||
addr: net::SocketAddr,
|
|
||||||
host: Option<String>,
|
|
||||||
keep_alive: KeepAlive,
|
|
||||||
_t: PhantomData<(H, Io)>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<H, F, Io> NewService for HttpService<H, F, Io>
|
|
||||||
where
|
|
||||||
H: HttpHandler,
|
|
||||||
F: IntoHttpHandler<Handler = H>,
|
|
||||||
Io: IoStream,
|
|
||||||
{
|
|
||||||
type Request = Io;
|
|
||||||
type Response = ();
|
|
||||||
type Error = ();
|
|
||||||
type InitError = ();
|
|
||||||
type Service = HttpServiceHandler<H, Io>;
|
|
||||||
type Future = FutureResult<Self::Service, Self::Error>;
|
|
||||||
|
|
||||||
fn new_service(&self) -> Self::Future {
|
|
||||||
let s = ServerSettings::new(Some(self.addr), &self.host, false);
|
|
||||||
let apps: Vec<_> = (*self.factory)()
|
|
||||||
.into_iter()
|
|
||||||
.map(|h| h.into_handler())
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
ok(HttpServiceHandler::new(apps, self.keep_alive, s))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<H, F, Io> Clone for HttpService<H, F, Io>
|
|
||||||
where
|
|
||||||
H: HttpHandler,
|
|
||||||
F: IntoHttpHandler<Handler = H>,
|
|
||||||
Io: IoStream,
|
|
||||||
{
|
|
||||||
fn clone(&self) -> HttpService<H, F, Io> {
|
|
||||||
HttpService {
|
|
||||||
addr: self.addr,
|
|
||||||
factory: self.factory.clone(),
|
|
||||||
host: self.host.clone(),
|
|
||||||
keep_alive: self.keep_alive,
|
|
||||||
_t: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<H: IntoHttpHandler> HttpServer<H> {
|
impl<H: IntoHttpHandler> HttpServer<H> {
|
||||||
/// Start listening for incoming connections.
|
/// Start listening for incoming connections.
|
||||||
///
|
///
|
||||||
@ -500,8 +454,9 @@ impl<H: IntoHttpHandler> HttpServer<H> {
|
|||||||
for socket in sockets {
|
for socket in sockets {
|
||||||
let Socket {
|
let Socket {
|
||||||
lst,
|
lst,
|
||||||
addr: _,
|
|
||||||
handler,
|
handler,
|
||||||
|
addr: _,
|
||||||
|
scheme: _,
|
||||||
} = socket;
|
} = socket;
|
||||||
srv = handler.register(srv, lst, self.host.clone(), self.keep_alive);
|
srv = handler.register(srv, lst, self.host.clone(), self.keep_alive);
|
||||||
}
|
}
|
||||||
@ -597,6 +552,43 @@ impl<H: IntoHttpHandler> HttpServer<H> {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
struct HttpService<H, F, Io>
|
||||||
|
where
|
||||||
|
H: HttpHandler,
|
||||||
|
F: IntoHttpHandler<Handler = H>,
|
||||||
|
Io: IoStream,
|
||||||
|
{
|
||||||
|
factory: Arc<Fn() -> Vec<F> + Send + Sync>,
|
||||||
|
addr: net::SocketAddr,
|
||||||
|
host: Option<String>,
|
||||||
|
keep_alive: KeepAlive,
|
||||||
|
_t: PhantomData<(H, Io)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<H, F, Io> NewService for HttpService<H, F, Io>
|
||||||
|
where
|
||||||
|
H: HttpHandler,
|
||||||
|
F: IntoHttpHandler<Handler = H>,
|
||||||
|
Io: IoStream,
|
||||||
|
{
|
||||||
|
type Request = Io;
|
||||||
|
type Response = ();
|
||||||
|
type Error = ();
|
||||||
|
type InitError = ();
|
||||||
|
type Service = HttpServiceHandler<H, Io>;
|
||||||
|
type Future = FutureResult<Self::Service, Self::Error>;
|
||||||
|
|
||||||
|
fn new_service(&self) -> Self::Future {
|
||||||
|
let s = ServerSettings::new(Some(self.addr), &self.host, false);
|
||||||
|
let apps: Vec<_> = (*self.factory)()
|
||||||
|
.into_iter()
|
||||||
|
.map(|h| h.into_handler())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
ok(HttpServiceHandler::new(apps, self.keep_alive, s))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct HttpServiceHandler<H, Io>
|
struct HttpServiceHandler<H, Io>
|
||||||
where
|
where
|
||||||
H: HttpHandler,
|
H: HttpHandler,
|
||||||
@ -656,21 +648,17 @@ where
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
trait IoStreamHandler<H>: Send
|
trait ServiceFactory<H>
|
||||||
where
|
where
|
||||||
H: IntoHttpHandler,
|
H: IntoHttpHandler,
|
||||||
{
|
{
|
||||||
fn addr(&self) -> net::SocketAddr;
|
|
||||||
|
|
||||||
fn scheme(&self) -> &'static str;
|
|
||||||
|
|
||||||
fn register(
|
fn register(
|
||||||
&self, server: Server, lst: net::TcpListener, host: Option<String>,
|
&self, server: Server, lst: net::TcpListener, host: Option<String>,
|
||||||
keep_alive: KeepAlive,
|
keep_alive: KeepAlive,
|
||||||
) -> Server;
|
) -> Server;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SimpleHandler<H>
|
struct SimpleFactory<H>
|
||||||
where
|
where
|
||||||
H: IntoHttpHandler,
|
H: IntoHttpHandler,
|
||||||
{
|
{
|
||||||
@ -678,27 +666,19 @@ where
|
|||||||
pub factory: Arc<Fn() -> Vec<H> + Send + Sync>,
|
pub factory: Arc<Fn() -> Vec<H> + Send + Sync>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<H: IntoHttpHandler> Clone for SimpleHandler<H> {
|
impl<H: IntoHttpHandler> Clone for SimpleFactory<H> {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
SimpleHandler {
|
SimpleFactory {
|
||||||
addr: self.addr,
|
addr: self.addr,
|
||||||
factory: self.factory.clone(),
|
factory: self.factory.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<H> IoStreamHandler<H> for SimpleHandler<H>
|
impl<H> ServiceFactory<H> for SimpleFactory<H>
|
||||||
where
|
where
|
||||||
H: IntoHttpHandler + 'static,
|
H: IntoHttpHandler + 'static,
|
||||||
{
|
{
|
||||||
fn addr(&self) -> net::SocketAddr {
|
|
||||||
self.addr
|
|
||||||
}
|
|
||||||
|
|
||||||
fn scheme(&self) -> &'static str {
|
|
||||||
"http"
|
|
||||||
}
|
|
||||||
|
|
||||||
fn register(
|
fn register(
|
||||||
&self, server: Server, lst: net::TcpListener, host: Option<String>,
|
&self, server: Server, lst: net::TcpListener, host: Option<String>,
|
||||||
keep_alive: KeepAlive,
|
keep_alive: KeepAlive,
|
||||||
@ -716,6 +696,59 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct AcceptorFactory<T, F, H>
|
||||||
|
where
|
||||||
|
F: Fn() -> T + Send + Clone + 'static,
|
||||||
|
T: NewService,
|
||||||
|
H: IntoHttpHandler,
|
||||||
|
{
|
||||||
|
pub addr: net::SocketAddr,
|
||||||
|
pub acceptor: F,
|
||||||
|
pub factory: Arc<Fn() -> Vec<H> + Send + Sync>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, F, H> Clone for AcceptorFactory<T, F, H>
|
||||||
|
where
|
||||||
|
F: Fn() -> T + Send + Clone + 'static,
|
||||||
|
T: NewService,
|
||||||
|
H: IntoHttpHandler,
|
||||||
|
{
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
AcceptorFactory {
|
||||||
|
addr: self.addr,
|
||||||
|
acceptor: self.acceptor.clone(),
|
||||||
|
factory: self.factory.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, F, H> ServiceFactory<H> for AcceptorFactory<T, F, H>
|
||||||
|
where
|
||||||
|
F: Fn() -> T + Send + Clone + 'static,
|
||||||
|
H: IntoHttpHandler + 'static,
|
||||||
|
T: NewService<Request = TcpStream, Error = (), InitError = ()> + Clone + 'static,
|
||||||
|
T::Response: IoStream,
|
||||||
|
{
|
||||||
|
fn register(
|
||||||
|
&self, server: Server, lst: net::TcpListener, host: Option<String>,
|
||||||
|
keep_alive: KeepAlive,
|
||||||
|
) -> Server {
|
||||||
|
let addr = self.addr;
|
||||||
|
let factory = self.factory.clone();
|
||||||
|
let acceptor = self.acceptor.clone();
|
||||||
|
|
||||||
|
server.listen(lst, move || {
|
||||||
|
(acceptor)().and_then(HttpService {
|
||||||
|
keep_alive,
|
||||||
|
addr,
|
||||||
|
host: host.clone(),
|
||||||
|
factory: factory.clone(),
|
||||||
|
_t: PhantomData,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn create_tcp_listener(
|
fn create_tcp_listener(
|
||||||
addr: net::SocketAddr, backlog: i32,
|
addr: net::SocketAddr, backlog: i32,
|
||||||
) -> io::Result<net::TcpListener> {
|
) -> io::Result<net::TcpListener> {
|
||||||
|
@ -115,6 +115,8 @@ use futures::{Async, Poll};
|
|||||||
use tokio_io::{AsyncRead, AsyncWrite};
|
use tokio_io::{AsyncRead, AsyncWrite};
|
||||||
use tokio_tcp::TcpStream;
|
use tokio_tcp::TcpStream;
|
||||||
|
|
||||||
|
pub use actix_net::{PauseServer, ResumeServer, StopServer};
|
||||||
|
|
||||||
mod channel;
|
mod channel;
|
||||||
mod error;
|
mod error;
|
||||||
pub(crate) mod h1;
|
pub(crate) mod h1;
|
||||||
@ -128,9 +130,9 @@ pub(crate) mod input;
|
|||||||
pub(crate) mod message;
|
pub(crate) mod message;
|
||||||
pub(crate) mod output;
|
pub(crate) mod output;
|
||||||
pub(crate) mod settings;
|
pub(crate) mod settings;
|
||||||
mod ssl;
|
|
||||||
|
|
||||||
use actix::Message;
|
mod ssl;
|
||||||
|
pub use self::ssl::*;
|
||||||
|
|
||||||
pub use self::http::HttpServer;
|
pub use self::http::HttpServer;
|
||||||
pub use self::message::Request;
|
pub use self::message::Request;
|
||||||
@ -221,40 +223,6 @@ impl From<Option<usize>> for KeepAlive {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pause accepting incoming connections
|
|
||||||
///
|
|
||||||
/// If socket contains some pending connection, they might be dropped.
|
|
||||||
/// All opened connection remains active.
|
|
||||||
#[derive(Message)]
|
|
||||||
pub struct PauseServer;
|
|
||||||
|
|
||||||
/// Resume accepting incoming connections
|
|
||||||
#[derive(Message)]
|
|
||||||
pub struct ResumeServer;
|
|
||||||
|
|
||||||
/// Stop incoming connection processing, stop all workers and exit.
|
|
||||||
///
|
|
||||||
/// If server starts with `spawn()` method, then spawned thread get terminated.
|
|
||||||
pub struct StopServer {
|
|
||||||
/// Whether to try and shut down gracefully
|
|
||||||
pub graceful: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Message for StopServer {
|
|
||||||
type Result = Result<(), ()>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Socket id token
|
|
||||||
#[doc(hidden)]
|
|
||||||
#[derive(Clone, Copy)]
|
|
||||||
pub struct Token(usize);
|
|
||||||
|
|
||||||
impl Token {
|
|
||||||
pub(crate) fn new(val: usize) -> Token {
|
|
||||||
Token(val)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Low level http request handler
|
/// Low level http request handler
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
pub trait HttpHandler: 'static {
|
pub trait HttpHandler: 'static {
|
||||||
|
@ -303,6 +303,8 @@ impl SharedBytesPool {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use futures::future;
|
||||||
|
use tokio::runtime::current_thread;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_date_len() {
|
fn test_date_len() {
|
||||||
@ -311,16 +313,20 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_date() {
|
fn test_date() {
|
||||||
let settings = WorkerSettings::<()>::new(
|
let mut rt = current_thread::Runtime::new().unwrap();
|
||||||
Vec::new(),
|
|
||||||
KeepAlive::Os,
|
let _ = rt.block_on(future::lazy(|| {
|
||||||
ServerSettings::default(),
|
let settings = WorkerSettings::<()>::new(
|
||||||
Connections::default(),
|
Vec::new(),
|
||||||
);
|
KeepAlive::Os,
|
||||||
let mut buf1 = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
|
ServerSettings::default(),
|
||||||
settings.set_date(&mut buf1, true);
|
);
|
||||||
let mut buf2 = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
|
let mut buf1 = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
|
||||||
settings.set_date(&mut buf2, true);
|
settings.set_date(&mut buf1, true);
|
||||||
assert_eq!(buf1, buf2);
|
let mut buf2 = BytesMut::with_capacity(DATE_VALUE_LENGTH + 10);
|
||||||
|
settings.set_date(&mut buf2, true);
|
||||||
|
assert_eq!(buf1, buf2);
|
||||||
|
future::ok::<_, ()>(())
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
#[cfg(feature = "alpn")]
|
#[cfg(any(feature = "alpn", feature = "ssl"))]
|
||||||
mod openssl;
|
mod openssl;
|
||||||
#[cfg(feature = "alpn")]
|
#[cfg(any(feature = "alpn", feature = "ssl"))]
|
||||||
pub use self::openssl::OpensslAcceptor;
|
pub use self::openssl::*;
|
||||||
|
|
||||||
#[cfg(feature = "tls")]
|
//#[cfg(feature = "tls")]
|
||||||
mod nativetls;
|
//mod nativetls;
|
||||||
#[cfg(feature = "tls")]
|
//#[cfg(feature = "tls")]
|
||||||
pub use self::nativetls::{NativeTlsAcceptor, TlsStream};
|
//pub use self::nativetls::{NativeTlsAcceptor, TlsStream};
|
||||||
|
|
||||||
#[cfg(feature = "rust-tls")]
|
//#[cfg(feature = "rust-tls")]
|
||||||
mod rustls;
|
//mod rustls;
|
||||||
#[cfg(feature = "rust-tls")]
|
//#[cfg(feature = "rust-tls")]
|
||||||
pub use self::rustls::RustlsAcceptor;
|
//pub use self::rustls::RustlsAcceptor;
|
||||||
|
@ -1,80 +1,41 @@
|
|||||||
use std::net::Shutdown;
|
use std::net::Shutdown;
|
||||||
use std::{io, time};
|
use std::{io, time};
|
||||||
|
|
||||||
use futures::{Future, Poll};
|
|
||||||
use openssl::ssl::{AlpnError, SslAcceptor, SslAcceptorBuilder};
|
use openssl::ssl::{AlpnError, SslAcceptor, SslAcceptorBuilder};
|
||||||
use tokio_openssl::{AcceptAsync, SslAcceptorExt, SslStream};
|
use tokio_openssl::SslStream;
|
||||||
|
|
||||||
use server::{AcceptorService, IoStream, ServerFlags};
|
use server::{IoStream, ServerFlags};
|
||||||
|
|
||||||
#[derive(Clone)]
|
/// Configure `SslAcceptorBuilder` with enabled `HTTP/2` and `HTTP1.1` support.
|
||||||
/// Support `SSL` connections via openssl package
|
pub fn openssl_acceptor(builder: SslAcceptorBuilder) -> io::Result<SslAcceptor> {
|
||||||
///
|
openssl_acceptor_with_flags(builder, ServerFlags::HTTP1 | ServerFlags::HTTP2)
|
||||||
/// `alpn` feature enables `OpensslAcceptor` type
|
|
||||||
pub struct OpensslAcceptor {
|
|
||||||
acceptor: SslAcceptor,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OpensslAcceptor {
|
/// Configure `SslAcceptorBuilder` with custom server flags.
|
||||||
/// Create `OpensslAcceptor` with enabled `HTTP/2` and `HTTP1.1` support.
|
pub fn openssl_acceptor_with_flags(
|
||||||
pub fn new(builder: SslAcceptorBuilder) -> io::Result<Self> {
|
mut builder: SslAcceptorBuilder, flags: ServerFlags,
|
||||||
OpensslAcceptor::with_flags(builder, ServerFlags::HTTP1 | ServerFlags::HTTP2)
|
) -> io::Result<SslAcceptor> {
|
||||||
|
let mut protos = Vec::new();
|
||||||
|
if flags.contains(ServerFlags::HTTP1) {
|
||||||
|
protos.extend(b"\x08http/1.1");
|
||||||
|
}
|
||||||
|
if flags.contains(ServerFlags::HTTP2) {
|
||||||
|
protos.extend(b"\x02h2");
|
||||||
|
builder.set_alpn_select_callback(|_, protos| {
|
||||||
|
const H2: &[u8] = b"\x02h2";
|
||||||
|
if protos.windows(3).any(|window| window == H2) {
|
||||||
|
Ok(b"h2")
|
||||||
|
} else {
|
||||||
|
Err(AlpnError::NOACK)
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create `OpensslAcceptor` with custom server flags.
|
if !protos.is_empty() {
|
||||||
pub fn with_flags(
|
builder.set_alpn_protos(&protos)?;
|
||||||
mut builder: SslAcceptorBuilder, flags: ServerFlags,
|
|
||||||
) -> io::Result<Self> {
|
|
||||||
let mut protos = Vec::new();
|
|
||||||
if flags.contains(ServerFlags::HTTP1) {
|
|
||||||
protos.extend(b"\x08http/1.1");
|
|
||||||
}
|
|
||||||
if flags.contains(ServerFlags::HTTP2) {
|
|
||||||
protos.extend(b"\x02h2");
|
|
||||||
builder.set_alpn_select_callback(|_, protos| {
|
|
||||||
const H2: &[u8] = b"\x02h2";
|
|
||||||
if protos.windows(3).any(|window| window == H2) {
|
|
||||||
Ok(b"h2")
|
|
||||||
} else {
|
|
||||||
Err(AlpnError::NOACK)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if !protos.is_empty() {
|
|
||||||
builder.set_alpn_protos(&protos)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(OpensslAcceptor {
|
|
||||||
acceptor: builder.build(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct AcceptorFut<Io>(AcceptAsync<Io>);
|
|
||||||
|
|
||||||
impl<Io: IoStream> Future for AcceptorFut<Io> {
|
|
||||||
type Item = SslStream<Io>;
|
|
||||||
type Error = io::Error;
|
|
||||||
|
|
||||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
|
||||||
self.0
|
|
||||||
.poll()
|
|
||||||
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<Io: IoStream> AcceptorService<Io> for OpensslAcceptor {
|
|
||||||
type Accepted = SslStream<Io>;
|
|
||||||
type Future = AcceptorFut<Io>;
|
|
||||||
|
|
||||||
fn scheme(&self) -> &'static str {
|
|
||||||
"https"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn accept(&self, io: Io) -> Self::Future {
|
Ok(builder.build())
|
||||||
AcceptorFut(SslAcceptorExt::accept_async(&self.acceptor, io))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: IoStream> IoStream for SslStream<T> {
|
impl<T: IoStream> IoStream for SslStream<T> {
|
||||||
|
@ -30,6 +30,7 @@ use modhttp::Request;
|
|||||||
use rand::distributions::Alphanumeric;
|
use rand::distributions::Alphanumeric;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use tokio::runtime::current_thread::Runtime;
|
use tokio::runtime::current_thread::Runtime;
|
||||||
|
use tokio_current_thread::spawn;
|
||||||
use tokio_tcp::TcpStream;
|
use tokio_tcp::TcpStream;
|
||||||
|
|
||||||
use actix_web::*;
|
use actix_web::*;
|
||||||
@ -904,7 +905,7 @@ fn test_h2() {
|
|||||||
let (response, _) = client.send_request(request, false).unwrap();
|
let (response, _) = client.send_request(request, false).unwrap();
|
||||||
|
|
||||||
// Spawn a task to run the conn...
|
// Spawn a task to run the conn...
|
||||||
current_thread::spawn(h2.map_err(|e| println!("GOT ERR={:?}", e)));
|
spawn(h2.map_err(|e| println!("GOT ERR={:?}", e)));
|
||||||
|
|
||||||
response.and_then(|response| {
|
response.and_then(|response| {
|
||||||
assert_eq!(response.status(), http::StatusCode::OK);
|
assert_eq!(response.status(), http::StatusCode::OK);
|
||||||
|
Loading…
Reference in New Issue
Block a user