fix(server): handle keep-alive closing

Closes #437
This commit is contained in:
Sean McArthur
2015-04-15 11:07:23 -07:00
parent dac2f4db8a
commit d9187713b2
2 changed files with 30 additions and 12 deletions

View File

@@ -12,7 +12,7 @@ use method::Method;
use status::StatusCode; use status::StatusCode;
use uri::RequestUri; use uri::RequestUri;
use version::HttpVersion::{self, Http10, Http11}; use version::HttpVersion::{self, Http10, Http11};
use HttpError:: HttpTooLargeError; use HttpError::{HttpIoError, HttpTooLargeError};
use {HttpError, HttpResult}; use {HttpError, HttpResult};
use self::HttpReader::{SizedReader, ChunkedReader, EofReader, EmptyReader}; use self::HttpReader::{SizedReader, ChunkedReader, EofReader, EmptyReader};
@@ -353,6 +353,12 @@ fn parse<R: Read, T: TryParse<Subject=I>, I>(rdr: &mut BufReader<R>) -> HttpResu
_partial => () _partial => ()
} }
match try!(rdr.read_into_buf()) { match try!(rdr.read_into_buf()) {
0 if rdr.get_buf().len() == 0 => {
return Err(HttpIoError(io::Error::new(
io::ErrorKind::ConnectionAborted,
"Connection closed"
)))
},
0 => return Err(HttpTooLargeError), 0 => return Err(HttpTooLargeError),
_ => () _ => ()
} }
@@ -417,6 +423,7 @@ impl<'a> TryParse for httparse::Response<'a> {
} }
/// An Incoming Message head. Includes request/status line, and headers. /// An Incoming Message head. Includes request/status line, and headers.
#[derive(Debug)]
pub struct Incoming<S> { pub struct Incoming<S> {
/// HTTP version of the message. /// HTTP version of the message.
pub version: HttpVersion, pub version: HttpVersion,
@@ -440,8 +447,10 @@ pub struct RawStatus(pub u16, pub Cow<'static, str>);
mod tests { mod tests {
use std::io::{self, Write}; use std::io::{self, Write};
use super::{read_chunk_size}; use buffer::BufReader;
use mock::MockStream;
use super::{read_chunk_size, parse_request};
#[test] #[test]
fn test_write_chunked() { fn test_write_chunked() {
@@ -509,25 +518,30 @@ mod tests {
#[test] #[test]
fn test_parse_incoming() { fn test_parse_incoming() {
use buffer::BufReader;
use mock::MockStream;
use super::parse_request;
let mut raw = MockStream::with_input(b"GET /echo HTTP/1.1\r\nHost: hyper.rs\r\n\r\n"); let mut raw = MockStream::with_input(b"GET /echo HTTP/1.1\r\nHost: hyper.rs\r\n\r\n");
let mut buf = BufReader::new(&mut raw); let mut buf = BufReader::new(&mut raw);
parse_request(&mut buf).unwrap(); parse_request(&mut buf).unwrap();
} }
#[test]
fn test_parse_tcp_closed() {
use std::io::ErrorKind;
use error::HttpError::HttpIoError;
let mut empty = MockStream::new();
let mut buf = BufReader::new(&mut empty);
match parse_request(&mut buf) {
Err(HttpIoError(ref e)) if e.kind() == ErrorKind::ConnectionAborted => (),
other => panic!("unexpected result: {:?}", other)
}
}
#[cfg(feature = "nightly")] #[cfg(feature = "nightly")]
use test::Bencher; use test::Bencher;
#[cfg(feature = "nightly")] #[cfg(feature = "nightly")]
#[bench] #[bench]
fn bench_parse_incoming(b: &mut Bencher) { fn bench_parse_incoming(b: &mut Bencher) {
use buffer::BufReader;
use mock::MockStream;
use super::parse_request;
let mut raw = MockStream::with_input(b"GET /echo HTTP/1.1\r\nHost: hyper.rs\r\n\r\n"); let mut raw = MockStream::with_input(b"GET /echo HTTP/1.1\r\nHost: hyper.rs\r\n\r\n");
let mut buf = BufReader::new(&mut raw); let mut buf = BufReader::new(&mut raw);
b.iter(|| { b.iter(|| {

View File

@@ -1,5 +1,5 @@
//! HTTP Server //! HTTP Server
use std::io::{BufWriter, Write}; use std::io::{ErrorKind, BufWriter, Write};
use std::marker::PhantomData; use std::marker::PhantomData;
use std::net::{SocketAddr, ToSocketAddrs}; use std::net::{SocketAddr, ToSocketAddrs};
use std::path::Path; use std::path::Path;
@@ -134,7 +134,11 @@ where S: NetworkStream + Clone, H: Handler {
while keep_alive { while keep_alive {
let req = match Request::new(&mut rdr, addr) { let req = match Request::new(&mut rdr, addr) {
Ok(req) => req, Ok(req) => req,
Err(e@HttpIoError(_)) => { Err(HttpIoError(ref e)) if e.kind() == ErrorKind::ConnectionAborted => {
trace!("tcp closed, cancelling keep-alive loop");
break;
}
Err(HttpIoError(e)) => {
debug!("ioerror in keepalive loop = {:?}", e); debug!("ioerror in keepalive loop = {:?}", e);
break; break;
} }