Skip to content

Commit

Permalink
feat(client): allow HTTP/0.9 responses behind a flag (fixes hyperium#…
Browse files Browse the repository at this point in the history
  • Loading branch information
nox committed Mar 22, 2021
1 parent 526e709 commit 8cbd505
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 3 deletions.
8 changes: 8 additions & 0 deletions src/client/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -972,6 +972,14 @@ impl Builder {
self
}

/// Set whether HTTP/0.9 responses should be tolerated.
///
/// Default is false.
pub fn http09_responses(&mut self, val: bool) -> &mut Self {
self.conn_builder.h09_responses(val);
self
}

/// Set whether the connection **must** use HTTP/2.
///
/// The destination must either allow HTTP2 Prior Knowledge, or the
Expand Down
10 changes: 10 additions & 0 deletions src/client/conn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ where
#[derive(Clone, Debug)]
pub struct Builder {
pub(super) exec: Exec,
h09_responses: bool,
h1_title_case_headers: bool,
h1_read_buf_exact_size: Option<usize>,
h1_max_buf_size: Option<usize>,
Expand Down Expand Up @@ -493,6 +494,7 @@ impl Builder {
pub fn new() -> Builder {
Builder {
exec: Exec::Default,
h09_responses: false,
h1_read_buf_exact_size: None,
h1_title_case_headers: false,
h1_max_buf_size: None,
Expand All @@ -514,6 +516,11 @@ impl Builder {
self
}

pub(super) fn h09_responses(&mut self, enabled: bool) -> &mut Builder {
self.h09_responses = enabled;
self
}

pub(super) fn h1_title_case_headers(&mut self, enabled: bool) -> &mut Builder {
self.h1_title_case_headers = enabled;
self
Expand Down Expand Up @@ -700,6 +707,9 @@ impl Builder {
if opts.h1_title_case_headers {
conn.set_title_case_headers();
}
if opts.h09_responses {
conn.set_h09_responses();
}
if let Some(sz) = opts.h1_read_buf_exact_size {
conn.set_read_buf_exact_size(sz);
}
Expand Down
8 changes: 8 additions & 0 deletions src/proto/h1/conn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ where
#[cfg(feature = "ffi")]
preserve_header_case: false,
title_case_headers: false,
h09_responses: false,
notify_read: false,
reading: Reading::Init,
writing: Writing::Init,
Expand Down Expand Up @@ -78,6 +79,11 @@ where
self.state.title_case_headers = true;
}

#[cfg(feature = "client")]
pub(crate) fn set_h09_responses(&mut self) {
self.state.h09_responses = true;
}

#[cfg(feature = "server")]
pub(crate) fn set_allow_half_close(&mut self) {
self.state.allow_half_close = true;
Expand Down Expand Up @@ -146,6 +152,7 @@ where
req_method: &mut self.state.method,
#[cfg(feature = "ffi")]
preserve_header_case: self.state.preserve_header_case,
h09_responses: self.state.h09_responses,
}
)) {
Ok(msg) => msg,
Expand Down Expand Up @@ -753,6 +760,7 @@ struct State {
#[cfg(feature = "ffi")]
preserve_header_case: bool,
title_case_headers: bool,
h09_responses: bool,
/// Set to true when the Dispatcher should poll read operations
/// again. See the `maybe_notify` method for more.
notify_read: bool,
Expand Down
2 changes: 2 additions & 0 deletions src/proto/h1/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ where
req_method: parse_ctx.req_method,
#[cfg(feature = "ffi")]
preserve_header_case: parse_ctx.preserve_header_case,
h09_responses: parse_ctx.h09_responses,
},
)? {
Some(msg) => {
Expand Down Expand Up @@ -640,6 +641,7 @@ mod tests {
req_method: &mut None,
#[cfg(feature = "ffi")]
preserve_header_case: false,
h09_responses: false,
};
assert!(buffered
.parse::<ClientTransaction>(cx, parse_ctx)
Expand Down
1 change: 1 addition & 0 deletions src/proto/h1/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ pub(crate) struct ParseContext<'a> {
req_method: &'a mut Option<Method>,
#[cfg(feature = "ffi")]
preserve_header_case: bool,
h09_responses: bool,
}

/// Passed to Http1Transaction::encode
Expand Down
28 changes: 25 additions & 3 deletions src/proto/h1/role.rs
Original file line number Diff line number Diff line change
Expand Up @@ -683,8 +683,8 @@ impl Http1Transaction for Client {
);
let mut res = httparse::Response::new(&mut headers);
let bytes = buf.as_ref();
match res.parse(bytes)? {
httparse::Status::Complete(len) => {
match res.parse(bytes) {
Ok(httparse::Status::Complete(len)) => {
trace!("Response.parse Complete({})", len);
let status = StatusCode::from_u16(res.code.unwrap())?;

Expand All @@ -710,7 +710,18 @@ impl Http1Transaction for Client {
let headers_len = res.headers.len();
(len, status, reason, version, headers_len)
}
httparse::Status::Partial => return Ok(None),
Ok(httparse::Status::Partial) => return Ok(None),
Err(httparse::Error::Version) if ctx.h09_responses => {
trace!("Response.parse accepted HTTP/0.9 response");

#[cfg(not(feature = "ffi"))]
let reason = ();
#[cfg(feature = "ffi")]
let reason = None;

(0, StatusCode::OK, reason, Version::HTTP_09, 0)
}
Err(e) => return Err(e.into()),
}
};

Expand Down Expand Up @@ -1222,6 +1233,7 @@ mod tests {
req_method: &mut method,
#[cfg(feature = "ffi")]
preserve_header_case: false,
h09_responses: false,
},
)
.unwrap()
Expand All @@ -1244,6 +1256,7 @@ mod tests {
req_method: &mut Some(crate::Method::GET),
#[cfg(feature = "ffi")]
preserve_header_case: false,
h09_responses: false,
};
let msg = Client::parse(&mut raw, ctx).unwrap().unwrap();
assert_eq!(raw.len(), 0);
Expand All @@ -1261,6 +1274,7 @@ mod tests {
req_method: &mut None,
#[cfg(feature = "ffi")]
preserve_header_case: false,
h09_responses: false,
};
Server::parse(&mut raw, ctx).unwrap_err();
}
Expand All @@ -1276,6 +1290,7 @@ mod tests {
req_method: &mut None,
#[cfg(feature = "ffi")]
preserve_header_case: false,
h09_responses: false,
},
)
.expect("parse ok")
Expand All @@ -1291,6 +1306,7 @@ mod tests {
req_method: &mut None,
#[cfg(feature = "ffi")]
preserve_header_case: false,
h09_responses: false,
},
)
.expect_err(comment)
Expand Down Expand Up @@ -1505,6 +1521,7 @@ mod tests {
req_method: &mut Some(Method::GET),
#[cfg(feature = "ffi")]
preserve_header_case: false,
h09_responses: false,
}
)
.expect("parse ok")
Expand All @@ -1520,6 +1537,7 @@ mod tests {
req_method: &mut Some(m),
#[cfg(feature = "ffi")]
preserve_header_case: false,
h09_responses: false,
},
)
.expect("parse ok")
Expand All @@ -1535,6 +1553,7 @@ mod tests {
req_method: &mut Some(Method::GET),
#[cfg(feature = "ffi")]
preserve_header_case: false,
h09_responses: false,
},
)
.expect_err("parse should err")
Expand Down Expand Up @@ -1850,6 +1869,7 @@ mod tests {
req_method: &mut Some(Method::GET),
#[cfg(feature = "ffi")]
preserve_header_case: false,
h09_responses: false,
},
)
.expect("parse ok")
Expand Down Expand Up @@ -1931,6 +1951,7 @@ mod tests {
req_method: &mut None,
#[cfg(feature = "ffi")]
preserve_header_case: false,
h09_responses: false,
},
)
.unwrap()
Expand Down Expand Up @@ -1966,6 +1987,7 @@ mod tests {
req_method: &mut None,
#[cfg(feature = "ffi")]
preserve_header_case: false,
h09_responses: false,
},
)
.unwrap()
Expand Down

0 comments on commit 8cbd505

Please sign in to comment.