1
0
mirror of https://github.com/fafhrd91/actix-web synced 2024-11-30 18:44:35 +01:00

fix ssh handshake timeout

This commit is contained in:
Nikolay Kim 2018-10-02 11:18:59 -07:00
parent 61c7534e03
commit 724668910b
4 changed files with 90 additions and 37 deletions

View File

@ -176,12 +176,15 @@ where
/// Applies timeout to request prcoessing. /// Applies timeout to request prcoessing.
pub(crate) struct AcceptorTimeout<T> { pub(crate) struct AcceptorTimeout<T> {
inner: T, inner: T,
timeout: u64, timeout: Duration,
} }
impl<T: NewService> AcceptorTimeout<T> { impl<T: NewService> AcceptorTimeout<T> {
pub(crate) fn new(timeout: u64, inner: T) -> Self { pub(crate) fn new(timeout: u64, inner: T) -> Self {
Self { inner, timeout } Self {
inner,
timeout: Duration::from_millis(timeout),
}
} }
} }
@ -204,7 +207,7 @@ impl<T: NewService> NewService for AcceptorTimeout<T> {
#[doc(hidden)] #[doc(hidden)]
pub(crate) struct AcceptorTimeoutFut<T: NewService> { pub(crate) struct AcceptorTimeoutFut<T: NewService> {
fut: T::Future, fut: T::Future,
timeout: u64, timeout: Duration,
} }
impl<T: NewService> Future for AcceptorTimeoutFut<T> { impl<T: NewService> Future for AcceptorTimeoutFut<T> {
@ -225,7 +228,7 @@ impl<T: NewService> Future for AcceptorTimeoutFut<T> {
/// Applies timeout to request prcoessing. /// Applies timeout to request prcoessing.
pub(crate) struct AcceptorTimeoutService<T> { pub(crate) struct AcceptorTimeoutService<T> {
inner: T, inner: T,
timeout: u64, timeout: Duration,
} }
impl<T: Service> Service for AcceptorTimeoutService<T> { impl<T: Service> Service for AcceptorTimeoutService<T> {
@ -241,7 +244,7 @@ impl<T: Service> Service for AcceptorTimeoutService<T> {
fn call(&mut self, req: Self::Request) -> Self::Future { fn call(&mut self, req: Self::Request) -> Self::Future {
AcceptorTimeoutResponse { AcceptorTimeoutResponse {
fut: self.inner.call(req), fut: self.inner.call(req),
sleep: sleep(Duration::from_millis(self.timeout)), sleep: sleep(self.timeout),
} }
} }
} }

View File

@ -59,18 +59,6 @@ where
); );
if secure { if secure {
Either::A(ServerMessageAcceptor::new(
settings.clone(),
TcpAcceptor::new(acceptor.create().map_err(AcceptorError::Service))
.map_err(|_| ())
.map_init_err(|_| ())
.and_then(
HttpService::new(settings)
.map_init_err(|_| ())
.map_err(|_| ()),
),
))
} else {
Either::B(ServerMessageAcceptor::new( Either::B(ServerMessageAcceptor::new(
settings.clone(), settings.clone(),
TcpAcceptor::new(AcceptorTimeout::new( TcpAcceptor::new(AcceptorTimeout::new(
@ -84,25 +72,23 @@ where
.map_err(|_| ()), .map_err(|_| ()),
), ),
)) ))
} else {
Either::A(ServerMessageAcceptor::new(
settings.clone(),
TcpAcceptor::new(acceptor.create().map_err(AcceptorError::Service))
.map_err(|_| ())
.map_init_err(|_| ())
.and_then(
HttpService::new(settings)
.map_init_err(|_| ())
.map_err(|_| ()),
),
))
} }
} }
} }
} }
impl<F, H, A> Clone for HttpServiceBuilder<F, H, A>
where
F: Fn() -> H + Send + Clone,
H: IntoHttpHandler,
A: AcceptorServiceFactory,
{
fn clone(&self) -> Self {
HttpServiceBuilder {
factory: self.factory.clone(),
acceptor: self.acceptor.clone(),
}
}
}
impl<F, H, A> ServiceProvider for HttpServiceBuilder<F, H, A> impl<F, H, A> ServiceProvider for HttpServiceBuilder<F, H, A>
where where
F: Fn() -> H + Send + Clone + 'static, F: Fn() -> H + Send + Clone + 'static,

View File

@ -15,6 +15,9 @@ extern crate tokio_current_thread as current_thread;
extern crate tokio_reactor; extern crate tokio_reactor;
extern crate tokio_tcp; extern crate tokio_tcp;
#[cfg(feature = "ssl")]
extern crate openssl;
use std::io::{Read, Write}; use std::io::{Read, Write};
use std::sync::Arc; use std::sync::Arc;
use std::{thread, time}; use std::{thread, time};
@ -1084,13 +1087,13 @@ fn test_slow_request() {
let mut stream = net::TcpStream::connect(addr).unwrap(); let mut stream = net::TcpStream::connect(addr).unwrap();
let mut data = String::new(); let mut data = String::new();
let _ = stream.read_to_string(&mut data); let _ = stream.read_to_string(&mut data);
assert!(data.starts_with("HTTP/1.1 408 Request Timeou")); assert!(data.starts_with("HTTP/1.1 408 Request Timeout"));
let mut stream = net::TcpStream::connect(addr).unwrap(); let mut stream = net::TcpStream::connect(addr).unwrap();
let _ = stream.write_all(b"GET /test/tests/test HTTP/1.1\r\n"); let _ = stream.write_all(b"GET /test/tests/test HTTP/1.1\r\n");
let mut data = String::new(); let mut data = String::new();
let _ = stream.read_to_string(&mut data); let _ = stream.read_to_string(&mut data);
assert!(data.starts_with("HTTP/1.1 408 Request Timeou")); assert!(data.starts_with("HTTP/1.1 408 Request Timeout"));
sys.stop(); sys.stop();
} }
@ -1106,9 +1109,9 @@ fn test_malformed_request() {
thread::spawn(move || { thread::spawn(move || {
System::run(move || { System::run(move || {
let srv = server::new(|| { let srv = server::new(|| {
vec![App::new().resource("/", |r| { App::new().resource("/", |r| {
r.method(http::Method::GET).f(|_| HttpResponse::Ok()) r.method(http::Method::GET).f(|_| HttpResponse::Ok())
})] })
}); });
let _ = srv.bind(addr).unwrap().start(); let _ = srv.bind(addr).unwrap().start();
@ -1126,3 +1129,64 @@ fn test_malformed_request() {
sys.stop(); sys.stop();
} }
#[test]
fn test_app_404() {
let mut srv = test::TestServer::with_factory(|| {
App::new().prefix("/prefix").resource("/", |r| {
r.method(http::Method::GET).f(|_| HttpResponse::Ok())
})
});
let request = srv.client(http::Method::GET, "/prefix/").finish().unwrap();
let response = srv.execute(request.send()).unwrap();
assert!(response.status().is_success());
let request = srv.client(http::Method::GET, "/").finish().unwrap();
let response = srv.execute(request.send()).unwrap();
assert_eq!(response.status(), http::StatusCode::NOT_FOUND);
}
#[test]
#[cfg(feature = "ssl")]
fn test_ssl_handshake_timeout() {
use actix::System;
use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod};
use std::net;
use std::sync::mpsc;
let (tx, rx) = mpsc::channel();
let addr = test::TestServer::unused_addr();
// load ssl keys
let mut builder = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap();
builder
.set_private_key_file("tests/key.pem", SslFiletype::PEM)
.unwrap();
builder
.set_certificate_chain_file("tests/cert.pem")
.unwrap();
thread::spawn(move || {
System::run(move || {
let srv = server::new(|| {
App::new().resource("/", |r| {
r.method(http::Method::GET).f(|_| HttpResponse::Ok())
})
});
srv.bind_ssl(addr, builder)
.unwrap()
.workers(1)
.client_timeout(200)
.start();
let _ = tx.send(System::current());
});
});
let sys = rx.recv().unwrap();
let mut stream = net::TcpStream::connect(addr).unwrap();
let mut data = String::new();
let _ = stream.read_to_string(&mut data);
assert!(data.is_empty())
}

View File

@ -14,7 +14,7 @@ use futures::Stream;
use rand::distributions::Alphanumeric; use rand::distributions::Alphanumeric;
use rand::Rng; use rand::Rng;
#[cfg(feature = "alpn")] #[cfg(feature = "ssl")]
extern crate openssl; extern crate openssl;
#[cfg(feature = "rust-tls")] #[cfg(feature = "rust-tls")]
extern crate rustls; extern crate rustls;
@ -282,7 +282,7 @@ fn test_server_send_bin() {
} }
#[test] #[test]
#[cfg(feature = "alpn")] #[cfg(feature = "ssl")]
fn test_ws_server_ssl() { fn test_ws_server_ssl() {
extern crate openssl; extern crate openssl;
use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod}; use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod};