Merge pull request #1135 from hyperium/server-keep-alive

fix(server): fix broken keep-alive in Server
This commit is contained in:
Sean McArthur
2017-04-13 11:24:36 -07:00
committed by GitHub
2 changed files with 73 additions and 3 deletions

View File

@@ -610,6 +610,9 @@ impl<B, K: KeepAlive> State<B, K> {
} }
fn busy(&mut self) { fn busy(&mut self) {
if let KA::Disabled = self.keep_alive.status() {
return;
}
self.keep_alive.busy(); self.keep_alive.busy();
} }

View File

@@ -146,10 +146,16 @@ fn connect(addr: &SocketAddr) -> TcpStream {
} }
fn serve() -> Serve { fn serve() -> Serve {
serve_with_timeout(None) serve_with_options(Default::default())
} }
fn serve_with_timeout(dur: Option<Duration>) -> Serve { #[derive(Default)]
struct ServeOptions {
keep_alive_disabled: bool,
timeout: Option<Duration>,
}
fn serve_with_options(options: ServeOptions) -> Serve {
let _ = pretty_env_logger::init(); let _ = pretty_env_logger::init();
let (addr_tx, addr_rx) = mpsc::channel(); let (addr_tx, addr_rx) = mpsc::channel();
@@ -159,9 +165,12 @@ fn serve_with_timeout(dur: Option<Duration>) -> Serve {
let addr = "127.0.0.1:0".parse().unwrap(); let addr = "127.0.0.1:0".parse().unwrap();
let keep_alive = !options.keep_alive_disabled;
let dur = options.timeout;
let thread_name = format!("test-server-{:?}", dur); let thread_name = format!("test-server-{:?}", dur);
let thread = thread::Builder::new().name(thread_name).spawn(move || { let thread = thread::Builder::new().name(thread_name).spawn(move || {
let srv = Http::new().bind(&addr, TestService { let srv = Http::new().keep_alive(keep_alive).bind(&addr, TestService {
tx: Arc::new(Mutex::new(msg_tx.clone())), tx: Arc::new(Mutex::new(msg_tx.clone())),
_timeout: dur, _timeout: dur,
reply: reply_rx, reply: reply_rx,
@@ -456,3 +465,61 @@ fn server_keep_alive() {
} }
} }
} }
#[test]
fn test_server_disable_keep_alive() {
let foo_bar = b"foo bar baz";
let server = serve_with_options(ServeOptions {
keep_alive_disabled: true,
.. Default::default()
});
server.reply()
.status(hyper::Ok)
.header(hyper::header::ContentLength(foo_bar.len() as u64))
.body(foo_bar);
let mut req = connect(server.addr());
req.write_all(b"\
GET / HTTP/1.1\r\n\
Host: example.domain\r\n\
Connection: keep-alive\r\n\
\r\n\
").expect("writing 1");
let mut buf = [0; 1024 * 8];
loop {
let n = req.read(&mut buf[..]).expect("reading 1");
if n < buf.len() {
if &buf[n - foo_bar.len()..n] == foo_bar {
break;
} else {
}
}
}
// try again!
let quux = b"zar quux";
server.reply()
.status(hyper::Ok)
.header(hyper::header::ContentLength(quux.len() as u64))
.body(quux);
let _ = req.write_all(b"\
GET /quux HTTP/1.1\r\n\
Host: example.domain\r\n\
Connection: close\r\n\
\r\n\
");
// the write can possibly succeed, since it fills the kernel buffer on the first write
let mut buf = [0; 1024 * 8];
match req.read(&mut buf[..]) {
// Ok(0) means EOF, so a proper shutdown
// Err(_) could mean ConnReset or something, also fine
Ok(0) |
Err(_) => {}
Ok(n) => {
panic!("read {} bytes on a disabled keep-alive socket", n);
}
}
}