fix(client): don't read extra bytes on idle connections
This commit is contained in:
@@ -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,
|
||||
}
|
||||
}
|
||||
@@ -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]
|
||||
|
||||
@@ -136,6 +136,10 @@ impl Http1Transaction for ServerTransaction {
|
||||
fn should_error_on_parse_eof() -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn should_read_first() -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl ServerTransaction {
|
||||
@@ -289,6 +293,10 @@ impl Http1Transaction for ClientTransaction {
|
||||
fn should_error_on_parse_eof() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn should_read_first() -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl ClientTransaction {
|
||||
|
||||
@@ -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)>>;
|
||||
|
||||
@@ -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,
|
||||
|
||||
|
||||
Reference in New Issue
Block a user