refactor(ffi): Add Reason-Phrase API

This adds an internal ability to copy the HTTP/1 reason-phrase and place
it in the `http::Extensions` of a response, if it doesn't match the
canonical reason. This could be exposed in the Rust API later, but for
now it is only used by the C API.
This commit is contained in:
Sean McArthur
2021-01-07 17:22:12 -08:00
parent 4c32daeea0
commit c9c46ed60b
5 changed files with 88 additions and 4 deletions

View File

@@ -5,6 +5,8 @@
use std::fmt::{self, Write};
use std::mem;
#[cfg(feature = "ffi")]
use bytes::Bytes;
use bytes::BytesMut;
use http::header::{self, Entry, HeaderName, HeaderValue};
use http::{HeaderMap, Method, StatusCode, Version};
@@ -660,7 +662,7 @@ impl Http1Transaction for Client {
loop {
// Unsafe: see comment in Server Http1Transaction, above.
let mut headers_indices: [HeaderIndices; MAX_HEADERS] = unsafe { mem::uninitialized() };
let (len, status, version, headers_len) = {
let (len, status, reason, version, headers_len) = {
let mut headers: [httparse::Header<'_>; MAX_HEADERS] =
unsafe { mem::uninitialized() };
trace!(
@@ -674,6 +676,20 @@ impl Http1Transaction for Client {
httparse::Status::Complete(len) => {
trace!("Response.parse Complete({})", len);
let status = StatusCode::from_u16(res.code.unwrap())?;
#[cfg(not(feature = "ffi"))]
let reason = ();
#[cfg(feature = "ffi")]
let reason = {
let reason = res.reason.unwrap();
// Only save the reason phrase if it isnt the canonical reason
if Some(reason) != status.canonical_reason() {
Some(Bytes::copy_from_slice(reason.as_bytes()))
} else {
None
}
};
let version = if res.version.unwrap() == 1 {
Version::HTTP_11
} else {
@@ -681,7 +697,7 @@ impl Http1Transaction for Client {
};
record_header_indices(bytes, &res.headers, &mut headers_indices)?;
let headers_len = res.headers.len();
(len, status, version, headers_len)
(len, status, reason, version, headers_len)
}
httparse::Status::Partial => return Ok(None),
}
@@ -728,6 +744,13 @@ impl Http1Transaction for Client {
extensions.insert(header_case_map);
}
#[cfg(feature = "ffi")]
if let Some(reason) = reason {
extensions.insert(crate::ffi::ReasonPhrase(reason));
}
#[cfg(not(feature = "ffi"))]
drop(reason);
let head = MessageHead {
version,
subject: status,