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 {
|
pub fn can_read_head(&self) -> bool {
|
||||||
match self.state.reading {
|
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,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -840,25 +849,35 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_conn_init_read_eof_busy() {
|
fn test_conn_init_read_eof_busy() {
|
||||||
// server ignores
|
let _: Result<(), ()> = future::lazy(|| {
|
||||||
let io = AsyncIo::new_buf(vec![], 1);
|
// server ignores
|
||||||
let mut conn = Conn::<_, proto::Chunk, ServerTransaction>::new(io, Default::default());
|
let io = AsyncIo::new_buf(vec![], 1);
|
||||||
conn.state.busy();
|
let mut conn = Conn::<_, proto::Chunk, ServerTransaction>::new(io, Default::default());
|
||||||
|
conn.state.busy();
|
||||||
|
|
||||||
match conn.poll().unwrap() {
|
match conn.poll().unwrap() {
|
||||||
Async::Ready(None) => {},
|
Async::Ready(None) => {},
|
||||||
other => panic!("unexpected frame: {:?}", other)
|
other => panic!("unexpected frame: {:?}", other)
|
||||||
}
|
}
|
||||||
|
|
||||||
// client, when busy, returns the error
|
// client
|
||||||
let io = AsyncIo::new_buf(vec![], 1);
|
let io = AsyncIo::new_buf(vec![], 1);
|
||||||
let mut conn = Conn::<_, proto::Chunk, ClientTransaction>::new(io, Default::default());
|
let mut conn = Conn::<_, proto::Chunk, ClientTransaction>::new(io, Default::default());
|
||||||
conn.state.busy();
|
conn.state.busy();
|
||||||
|
|
||||||
match conn.poll() {
|
match conn.poll() {
|
||||||
Err(ref err) if err.kind() == ::std::io::ErrorKind::UnexpectedEof => {},
|
Ok(Async::NotReady) => {},
|
||||||
other => panic!("unexpected frame: {:?}", other)
|
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]
|
#[test]
|
||||||
|
|||||||
@@ -136,6 +136,10 @@ impl Http1Transaction for ServerTransaction {
|
|||||||
fn should_error_on_parse_eof() -> bool {
|
fn should_error_on_parse_eof() -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn should_read_first() -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerTransaction {
|
impl ServerTransaction {
|
||||||
@@ -289,6 +293,10 @@ impl Http1Transaction for ClientTransaction {
|
|||||||
fn should_error_on_parse_eof() -> bool {
|
fn should_error_on_parse_eof() -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn should_read_first() -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClientTransaction {
|
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 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_error_on_parse_eof() -> bool;
|
||||||
|
fn should_read_first() -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type ParseResult<T> = ::Result<Option<(MessageHead<T>, usize)>>;
|
pub type ParseResult<T> = ::Result<Option<(MessageHead<T>, usize)>>;
|
||||||
|
|||||||
@@ -353,6 +353,38 @@ test! {
|
|||||||
body: None,
|
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! {
|
test! {
|
||||||
name: client_error_unexpected_eof,
|
name: client_error_unexpected_eof,
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user