Merge pull request #455 from hyperium/issue-437
fix(server): handle keep-alive closing
This commit is contained in:
34
src/http.rs
34
src/http.rs
@@ -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};
|
||||
@@ -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),
|
||||
_ => ()
|
||||
}
|
||||
@@ -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,
|
||||
@@ -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() {
|
||||
@@ -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(|| {
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user