Skip to content

Commit d6848e7

Browse files
committed
feat(server): Allow keep alive to be turned off for a connection
Closes hyperium#1365
1 parent cecef9d commit d6848e7

File tree

4 files changed

+70
-2
lines changed

4 files changed

+70
-2
lines changed

Diff for: src/proto/conn.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,10 @@ where I: AsyncRead + AsyncWrite,
453453
pub fn close_write(&mut self) {
454454
self.state.close_write();
455455
}
456+
457+
pub fn disable_keep_alive(&mut self) {
458+
self.state.disable_keep_alive();
459+
}
456460
}
457461

458462
// ==== tokio_proto impl ====
@@ -700,6 +704,10 @@ impl<B, K: KeepAlive> State<B, K> {
700704
}
701705
}
702706

707+
fn disable_keep_alive(&mut self) {
708+
self.keep_alive.disable()
709+
}
710+
703711
fn busy(&mut self) {
704712
if let KA::Disabled = self.keep_alive.status() {
705713
return;
@@ -869,7 +877,7 @@ mod tests {
869877
other => panic!("unexpected frame: {:?}", other)
870878
}
871879

872-
// client
880+
// client
873881
let io = AsyncIo::new_buf(vec![], 1);
874882
let mut conn = Conn::<_, proto::Chunk, ClientTransaction>::new(io, Default::default());
875883
conn.state.busy();

Diff for: src/proto/dispatch.rs

+4
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ where
5454
}
5555
}
5656

57+
pub fn disable_keep_alive(&mut self) {
58+
self.conn.disable_keep_alive()
59+
}
60+
5761
fn poll_read(&mut self) -> Poll<(), ::Error> {
5862
loop {
5963
if self.conn.can_read_head() {

Diff for: src/server/mod.rs

+12
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,18 @@ where
536536
}
537537
}
538538

539+
impl<I, B, S> Connection<I, S>
540+
where S: Service<Request = Request, Response = Response<B>, Error = ::Error> + 'static,
541+
I: AsyncRead + AsyncWrite + 'static,
542+
B: Stream<Error=::Error> + 'static,
543+
B::Item: AsRef<[u8]>,
544+
{
545+
/// Disables keep-alive for this connection.
546+
pub fn disable_keep_alive(&mut self) {
547+
self.conn.disable_keep_alive()
548+
}
549+
}
550+
539551
mod unnameable {
540552
// This type is specifically not exported outside the crate,
541553
// so no one can actually name the type. With no methods, we make no

Diff for: tests/server.rs

+45-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ extern crate pretty_env_logger;
66
extern crate tokio_core;
77

88
use futures::{Future, Stream};
9-
use futures::future::{self, FutureResult};
9+
use futures::future::{self, FutureResult, Either};
1010
use futures::sync::oneshot;
1111

1212
use tokio_core::net::TcpListener;
@@ -551,6 +551,50 @@ fn pipeline_enabled() {
551551
assert_eq!(n, 0);
552552
}
553553

554+
#[test]
555+
fn disable_keep_alive_mid_request() {
556+
let mut core = Core::new().unwrap();
557+
let listener = TcpListener::bind(&"127.0.0.1:0".parse().unwrap(), &core.handle()).unwrap();
558+
let addr = listener.local_addr().unwrap();
559+
560+
let (tx1, rx1) = oneshot::channel();
561+
let (tx2, rx2) = oneshot::channel();
562+
563+
let child = thread::spawn(move || {
564+
let mut req = connect(&addr);
565+
req.write_all(b"GET / HTTP/1.1\r\nConnection: keep-alive\r\n").unwrap();
566+
tx1.send(()).unwrap();
567+
rx2.wait().unwrap();
568+
req.write_all(b"Host: localhost\r\nContent-Length: 0\r\n\r\n").unwrap();
569+
let mut buf = vec![];
570+
req.read_to_end(&mut buf).unwrap();
571+
});
572+
573+
let fut = listener.incoming()
574+
.into_future()
575+
.map_err(|_| unreachable!())
576+
.and_then(|(item, _incoming)| {
577+
let (socket, _) = item.unwrap();
578+
Http::<hyper::Chunk>::new().serve_connection(socket, HelloWorld)
579+
.select2(rx1)
580+
.then(|r| {
581+
match r {
582+
Ok(Either::A(_)) => panic!("expected rx first"),
583+
Ok(Either::B(((), mut conn))) => {
584+
conn.disable_keep_alive();
585+
tx2.send(()).unwrap();
586+
conn
587+
}
588+
Err(Either::A((e, _))) => panic!("unexpected error {}", e),
589+
Err(Either::B((e, _))) => panic!("unexpected error {}", e),
590+
}
591+
})
592+
});
593+
594+
core.run(fut).unwrap();
595+
child.join().unwrap();
596+
}
597+
554598
#[test]
555599
fn no_proto_empty_parse_eof_does_not_return_error() {
556600
let mut core = Core::new().unwrap();

0 commit comments

Comments
 (0)