Skip to content

Commit 2277422

Browse files
committed
fix(client): error on unsupport 101 responses, ignore other 1xx codes
1 parent d8b1aa8 commit 2277422

File tree

5 files changed

+222
-97
lines changed

5 files changed

+222
-97
lines changed

src/error.rs

+11-7
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use self::Error::{
1616
Header,
1717
Status,
1818
Timeout,
19+
Upgrade,
1920
Io,
2021
TooLarge,
2122
Incomplete,
@@ -44,6 +45,8 @@ pub enum Error {
4445
Status,
4546
/// A timeout occurred waiting for an IO event.
4647
Timeout,
48+
/// A protocol upgrade was encountered, but not yet supported in hyper.
49+
Upgrade,
4750
/// An `io::Error` that occurred while trying to read or write to a network stream.
4851
Io(IoError),
4952
/// Parsing a field as string failed
@@ -76,13 +79,14 @@ impl fmt::Display for Error {
7679
impl StdError for Error {
7780
fn description(&self) -> &str {
7881
match *self {
79-
Method => "Invalid Method specified",
80-
Version => "Invalid HTTP version specified",
81-
Header => "Invalid Header provided",
82-
TooLarge => "Message head is too large",
83-
Status => "Invalid Status provided",
84-
Incomplete => "Message is incomplete",
85-
Timeout => "Timeout",
82+
Method => "invalid Method specified",
83+
Version => "invalid HTTP version specified",
84+
Header => "invalid Header provided",
85+
TooLarge => "message head is too large",
86+
Status => "invalid Status provided",
87+
Incomplete => "message is incomplete",
88+
Timeout => "timeout",
89+
Upgrade => "unsupported protocol upgrade",
8690
Uri(ref e) => e.description(),
8791
Io(ref e) => e.description(),
8892
Utf8(ref e) => e.description(),

src/proto/conn.rs

+60-54
Original file line numberDiff line numberDiff line change
@@ -171,65 +171,71 @@ where I: AsyncRead + AsyncWrite,
171171
debug_assert!(self.can_read_head());
172172
trace!("Conn::read_head");
173173

174-
let (version, head) = match self.io.parse::<T>() {
175-
Ok(Async::Ready(head)) => (head.version, head),
176-
Ok(Async::NotReady) => return Ok(Async::NotReady),
177-
Err(e) => {
178-
// If we are currently waiting on a message, then an empty
179-
// message should be reported as an error. If not, it is just
180-
// the connection closing gracefully.
181-
let must_error = self.should_error_on_eof();
182-
self.state.close_read();
183-
self.io.consume_leading_lines();
184-
let was_mid_parse = !self.io.read_buf().is_empty();
185-
return if was_mid_parse || must_error {
186-
debug!("parse error ({}) with {} bytes", e, self.io.read_buf().len());
187-
Err(e)
188-
} else {
189-
debug!("read eof");
190-
Ok(Async::Ready(None))
191-
};
192-
}
193-
};
174+
loop {
175+
let (version, head) = match self.io.parse::<T>() {
176+
Ok(Async::Ready(head)) => (head.version, head),
177+
Ok(Async::NotReady) => return Ok(Async::NotReady),
178+
Err(e) => {
179+
// If we are currently waiting on a message, then an empty
180+
// message should be reported as an error. If not, it is just
181+
// the connection closing gracefully.
182+
let must_error = self.should_error_on_eof();
183+
self.state.close_read();
184+
self.io.consume_leading_lines();
185+
let was_mid_parse = !self.io.read_buf().is_empty();
186+
return if was_mid_parse || must_error {
187+
debug!("parse error ({}) with {} bytes", e, self.io.read_buf().len());
188+
Err(e)
189+
} else {
190+
debug!("read eof");
191+
Ok(Async::Ready(None))
192+
};
193+
}
194+
};
194195

195-
self.state.version = match version {
196-
HttpVersion::Http10 => Version::Http10,
197-
HttpVersion::Http11 => Version::Http11,
198-
_ => {
199-
error!("unimplemented HTTP Version = {:?}", version);
200-
self.state.close_read();
201-
return Err(::Error::Version);
202-
}
203-
};
196+
self.state.version = match version {
197+
HttpVersion::Http10 => Version::Http10,
198+
HttpVersion::Http11 => Version::Http11,
199+
_ => {
200+
error!("unimplemented HTTP Version = {:?}", version);
201+
self.state.close_read();
202+
return Err(::Error::Version);
203+
}
204+
};
204205

205-
let decoder = match T::decoder(&head, &mut self.state.method) {
206-
Ok(d) => d,
207-
Err(e) => {
208-
debug!("decoder error = {:?}", e);
209-
self.state.close_read();
210-
return Err(e);
211-
}
212-
};
206+
let decoder = match T::decoder(&head, &mut self.state.method) {
207+
Ok(Some(d)) => d,
208+
Ok(None) => {
209+
// likely a 1xx message that we can ignore
210+
continue;
211+
}
212+
Err(e) => {
213+
debug!("decoder error = {:?}", e);
214+
self.state.close_read();
215+
return Err(e);
216+
}
217+
};
213218

214-
debug!("incoming body is {}", decoder);
219+
debug!("incoming body is {}", decoder);
215220

216-
self.state.busy();
217-
if head.expecting_continue() {
218-
let msg = b"HTTP/1.1 100 Continue\r\n\r\n";
219-
self.state.writing = Writing::Continue(Cursor::new(msg));
220-
}
221-
let wants_keep_alive = head.should_keep_alive();
222-
self.state.keep_alive &= wants_keep_alive;
223-
let (body, reading) = if decoder.is_eof() {
224-
(false, Reading::KeepAlive)
225-
} else {
226-
(true, Reading::Body(decoder))
227-
};
228-
self.state.reading = reading;
229-
if !body {
230-
self.try_keep_alive();
221+
self.state.busy();
222+
if head.expecting_continue() {
223+
let msg = b"HTTP/1.1 100 Continue\r\n\r\n";
224+
self.state.writing = Writing::Continue(Cursor::new(msg));
225+
}
226+
let wants_keep_alive = head.should_keep_alive();
227+
self.state.keep_alive &= wants_keep_alive;
228+
let (body, reading) = if decoder.is_eof() {
229+
(false, Reading::KeepAlive)
230+
} else {
231+
(true, Reading::Body(decoder))
232+
};
233+
self.state.reading = reading;
234+
if !body {
235+
self.try_keep_alive();
236+
}
237+
return Ok(Async::Ready(Some((head, body))));
231238
}
232-
Ok(Async::Ready(Some((head, body))))
233239
}
234240

235241
pub fn read_body(&mut self) -> Poll<Option<super::Chunk>, io::Error> {

0 commit comments

Comments
 (0)