Skip to content

Commit

Permalink
fix(client): don't read extra bytes on idle connections
Browse files Browse the repository at this point in the history
  • Loading branch information
seanmonstar committed Oct 27, 2017
1 parent f7532b7 commit 7c4b814
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 17 deletions.
53 changes: 36 additions & 17 deletions src/proto/conn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,16 @@ where I: AsyncRead + AsyncWrite,

pub fn can_read_head(&self) -> bool {
match self.state.reading {
Reading::Init => true,
Reading::Init => {
if T::should_read_first() {
true
} else {
match self.state.writing {
Writing::Init => false,
_ => true,
}
}
}
_ => false,
}
}
Expand Down Expand Up @@ -840,25 +849,35 @@ mod tests {

#[test]
fn test_conn_init_read_eof_busy() {
// server ignores
let io = AsyncIo::new_buf(vec![], 1);
let mut conn = Conn::<_, proto::Chunk, ServerTransaction>::new(io, Default::default());
conn.state.busy();
let _: Result<(), ()> = future::lazy(|| {
// server ignores
let io = AsyncIo::new_buf(vec![], 1);
let mut conn = Conn::<_, proto::Chunk, ServerTransaction>::new(io, Default::default());
conn.state.busy();

match conn.poll().unwrap() {
Async::Ready(None) => {},
other => panic!("unexpected frame: {:?}", other)
}
match conn.poll().unwrap() {
Async::Ready(None) => {},
other => panic!("unexpected frame: {:?}", other)
}

// client, when busy, returns the error
let io = AsyncIo::new_buf(vec![], 1);
let mut conn = Conn::<_, proto::Chunk, ClientTransaction>::new(io, Default::default());
conn.state.busy();
// client
let io = AsyncIo::new_buf(vec![], 1);
let mut conn = Conn::<_, proto::Chunk, ClientTransaction>::new(io, Default::default());
conn.state.busy();

match conn.poll() {
Err(ref err) if err.kind() == ::std::io::ErrorKind::UnexpectedEof => {},
other => panic!("unexpected frame: {:?}", other)
}
match conn.poll() {
Ok(Async::NotReady) => {},
other => panic!("unexpected frame: {:?}", other)
}

// once mid-request, returns the error
conn.state.writing = super::Writing::KeepAlive;
match conn.poll() {
Err(ref err) if err.kind() == ::std::io::ErrorKind::UnexpectedEof => {},
other => panic!("unexpected frame: {:?}", other)
}
Ok(())
}).wait();
}

#[test]
Expand Down
8 changes: 8 additions & 0 deletions src/proto/h1/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,10 @@ impl Http1Transaction for ServerTransaction {
fn should_error_on_parse_eof() -> bool {
false
}

fn should_read_first() -> bool {
true
}
}

impl ServerTransaction {
Expand Down Expand Up @@ -289,6 +293,10 @@ impl Http1Transaction for ClientTransaction {
fn should_error_on_parse_eof() -> bool {
true
}

fn should_read_first() -> bool {
false
}
}

impl ClientTransaction {
Expand Down
1 change: 1 addition & 0 deletions src/proto/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ pub trait Http1Transaction {
fn encode(head: MessageHead<Self::Outgoing>, has_body: bool, method: &mut Option<Method>, dst: &mut Vec<u8>) -> h1::Encoder;

fn should_error_on_parse_eof() -> bool;
fn should_read_first() -> bool;
}

pub type ParseResult<T> = ::Result<Option<(MessageHead<T>, usize)>>;
Expand Down
32 changes: 32 additions & 0 deletions tests/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,38 @@ test! {
body: None,
}

test! {
name: client_pipeline_responses_extra,

server:
expected: "\
GET /pipe HTTP/1.1\r\n\
Host: {addr}\r\n\
\r\n\
",
reply: "\
HTTP/1.1 200 OK\r\n\
Content-Length: 0\r\n\
\r\n\
HTTP/1.1 200 OK\r\n\
Content-Length: 0\r\n\
\r\n\
",

client:
request:
method: Get,
url: "http://{addr}/pipe",
headers: [],
body: None,
proxy: false,
response:
status: Ok,
headers: [],
body: None,
}


test! {
name: client_error_unexpected_eof,

Expand Down

0 comments on commit 7c4b814

Please sign in to comment.