Skip to content

Commit

Permalink
fix(server): handle keep-alive closing
Browse files Browse the repository at this point in the history
Closes #437
  • Loading branch information
seanmonstar committed Apr 16, 2015
1 parent dac2f4d commit d918771
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 12 deletions.
34 changes: 24 additions & 10 deletions src/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use method::Method;
use status::StatusCode;
use uri::RequestUri;
use version::HttpVersion::{self, Http10, Http11};
use HttpError:: HttpTooLargeError;
use HttpError::{HttpIoError, HttpTooLargeError};
use {HttpError, HttpResult};

use self::HttpReader::{SizedReader, ChunkedReader, EofReader, EmptyReader};
Expand Down Expand Up @@ -353,6 +353,12 @@ fn parse<R: Read, T: TryParse<Subject=I>, I>(rdr: &mut BufReader<R>) -> HttpResu
_partial => ()
}
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),
_ => ()
}
Expand Down Expand Up @@ -417,6 +423,7 @@ impl<'a> TryParse for httparse::Response<'a> {
}

/// An Incoming Message head. Includes request/status line, and headers.
#[derive(Debug)]
pub struct Incoming<S> {
/// HTTP version of the message.
pub version: HttpVersion,
Expand All @@ -440,8 +447,10 @@ pub struct RawStatus(pub u16, pub Cow<'static, str>);
mod tests {
use std::io::{self, Write};

use super::{read_chunk_size};
use buffer::BufReader;
use mock::MockStream;

use super::{read_chunk_size, parse_request};

#[test]
fn test_write_chunked() {
Expand Down Expand Up @@ -509,25 +518,30 @@ mod tests {

#[test]
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 buf = BufReader::new(&mut raw);
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")]
use test::Bencher;

#[cfg(feature = "nightly")]
#[bench]
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 buf = BufReader::new(&mut raw);
b.iter(|| {
Expand Down
8 changes: 6 additions & 2 deletions src/server/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//! HTTP Server
use std::io::{BufWriter, Write};
use std::io::{ErrorKind, BufWriter, Write};
use std::marker::PhantomData;
use std::net::{SocketAddr, ToSocketAddrs};
use std::path::Path;
Expand Down Expand Up @@ -134,7 +134,11 @@ where S: NetworkStream + Clone, H: Handler {
while keep_alive {
let req = match Request::new(&mut rdr, addr) {
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);
break;
}
Expand Down

0 comments on commit d918771

Please sign in to comment.