feat(ffi): add option to get raw headers from response
This commit is contained in:
@@ -371,6 +371,17 @@ void hyper_clientconn_options_exec(struct hyper_clientconn_options *opts,
|
|||||||
*/
|
*/
|
||||||
enum hyper_code hyper_clientconn_options_http2(struct hyper_clientconn_options *opts, int enabled);
|
enum hyper_code hyper_clientconn_options_http2(struct hyper_clientconn_options *opts, int enabled);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Set the whether to include a copy of the raw headers in responses
|
||||||
|
received on this connection.
|
||||||
|
|
||||||
|
Pass `0` to disable, `1` to enable.
|
||||||
|
|
||||||
|
If enabled, see `hyper_response_headers_raw()` for usage.
|
||||||
|
*/
|
||||||
|
enum hyper_code hyper_clientconn_options_headers_raw(struct hyper_clientconn_options *opts,
|
||||||
|
int enabled);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Frees a `hyper_error`.
|
Frees a `hyper_error`.
|
||||||
*/
|
*/
|
||||||
@@ -475,6 +486,21 @@ const uint8_t *hyper_response_reason_phrase(const struct hyper_response *resp);
|
|||||||
*/
|
*/
|
||||||
size_t hyper_response_reason_phrase_len(const struct hyper_response *resp);
|
size_t hyper_response_reason_phrase_len(const struct hyper_response *resp);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Get a reference to the full raw headers of this response.
|
||||||
|
|
||||||
|
You must have enabled `hyper_clientconn_options_headers_raw()`, or this
|
||||||
|
will return NULL.
|
||||||
|
|
||||||
|
The returned `hyper_buf *` is just a reference, owned by the response.
|
||||||
|
You need to make a copy if you wish to use it after freeing the
|
||||||
|
response.
|
||||||
|
|
||||||
|
The buffer is not null-terminated, see the `hyper_buf` functions for
|
||||||
|
getting the bytes and length.
|
||||||
|
*/
|
||||||
|
const struct hyper_buf *hyper_response_headers_raw(const struct hyper_response *resp);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Get the HTTP version used by this response.
|
Get the HTTP version used by this response.
|
||||||
|
|
||||||
|
|||||||
@@ -147,6 +147,8 @@ pub struct Builder {
|
|||||||
h1_preserve_header_case: bool,
|
h1_preserve_header_case: bool,
|
||||||
h1_read_buf_exact_size: Option<usize>,
|
h1_read_buf_exact_size: Option<usize>,
|
||||||
h1_max_buf_size: Option<usize>,
|
h1_max_buf_size: Option<usize>,
|
||||||
|
#[cfg(feature = "ffi")]
|
||||||
|
h1_headers_raw: bool,
|
||||||
#[cfg(feature = "http2")]
|
#[cfg(feature = "http2")]
|
||||||
h2_builder: proto::h2::client::Config,
|
h2_builder: proto::h2::client::Config,
|
||||||
version: Proto,
|
version: Proto,
|
||||||
@@ -528,6 +530,8 @@ impl Builder {
|
|||||||
h1_title_case_headers: false,
|
h1_title_case_headers: false,
|
||||||
h1_preserve_header_case: false,
|
h1_preserve_header_case: false,
|
||||||
h1_max_buf_size: None,
|
h1_max_buf_size: None,
|
||||||
|
#[cfg(feature = "ffi")]
|
||||||
|
h1_headers_raw: false,
|
||||||
#[cfg(feature = "http2")]
|
#[cfg(feature = "http2")]
|
||||||
h2_builder: Default::default(),
|
h2_builder: Default::default(),
|
||||||
#[cfg(feature = "http1")]
|
#[cfg(feature = "http1")]
|
||||||
@@ -588,6 +592,12 @@ impl Builder {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ffi")]
|
||||||
|
pub(crate) fn http1_headers_raw(&mut self, enabled: bool) -> &mut Self {
|
||||||
|
self.h1_headers_raw = enabled;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Sets whether HTTP2 is required.
|
/// Sets whether HTTP2 is required.
|
||||||
///
|
///
|
||||||
/// Default is false.
|
/// Default is false.
|
||||||
@@ -773,6 +783,10 @@ impl Builder {
|
|||||||
if opts.h09_responses {
|
if opts.h09_responses {
|
||||||
conn.set_h09_responses();
|
conn.set_h09_responses();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ffi")]
|
||||||
|
conn.set_raw_headers(opts.h1_headers_raw);
|
||||||
|
|
||||||
if let Some(sz) = opts.h1_read_buf_exact_size {
|
if let Some(sz) = opts.h1_read_buf_exact_size {
|
||||||
conn.set_read_buf_exact_size(sz);
|
conn.set_read_buf_exact_size(sz);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ use crate::body::{Body, Bytes, HttpBody as _};
|
|||||||
pub struct hyper_body(pub(super) Body);
|
pub struct hyper_body(pub(super) Body);
|
||||||
|
|
||||||
/// A buffer of bytes that is sent or received on a `hyper_body`.
|
/// A buffer of bytes that is sent or received on a `hyper_body`.
|
||||||
pub struct hyper_buf(pub(super) Bytes);
|
pub struct hyper_buf(pub(crate) Bytes);
|
||||||
|
|
||||||
pub(crate) struct UserBody {
|
pub(crate) struct UserBody {
|
||||||
data_func: hyper_body_data_callback,
|
data_func: hyper_body_data_callback,
|
||||||
|
|||||||
@@ -159,3 +159,17 @@ ffi_fn! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ffi_fn! {
|
||||||
|
/// Set the whether to include a copy of the raw headers in responses
|
||||||
|
/// received on this connection.
|
||||||
|
///
|
||||||
|
/// Pass `0` to disable, `1` to enable.
|
||||||
|
///
|
||||||
|
/// If enabled, see `hyper_response_headers_raw()` for usage.
|
||||||
|
fn hyper_clientconn_options_headers_raw(opts: *mut hyper_clientconn_options, enabled: c_int) -> hyper_code {
|
||||||
|
let opts = unsafe { &mut *opts };
|
||||||
|
opts.builder.http1_headers_raw(enabled != 0);
|
||||||
|
hyper_code::HYPERE_OK
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use bytes::Bytes;
|
|||||||
use libc::{c_int, size_t};
|
use libc::{c_int, size_t};
|
||||||
use std::ffi::c_void;
|
use std::ffi::c_void;
|
||||||
|
|
||||||
use super::body::hyper_body;
|
use super::body::{hyper_body, hyper_buf};
|
||||||
use super::error::hyper_code;
|
use super::error::hyper_code;
|
||||||
use super::task::{hyper_task_return_type, AsTaskType};
|
use super::task::{hyper_task_return_type, AsTaskType};
|
||||||
use super::HYPER_ITER_CONTINUE;
|
use super::HYPER_ITER_CONTINUE;
|
||||||
@@ -27,6 +27,8 @@ pub struct hyper_headers {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct ReasonPhrase(pub(crate) Bytes);
|
pub(crate) struct ReasonPhrase(pub(crate) Bytes);
|
||||||
|
|
||||||
|
pub(crate) struct RawHeaders(pub(crate) hyper_buf);
|
||||||
|
|
||||||
// ===== impl hyper_request =====
|
// ===== impl hyper_request =====
|
||||||
|
|
||||||
ffi_fn! {
|
ffi_fn! {
|
||||||
@@ -178,6 +180,26 @@ ffi_fn! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ffi_fn! {
|
||||||
|
/// Get a reference to the full raw headers of this response.
|
||||||
|
///
|
||||||
|
/// You must have enabled `hyper_clientconn_options_headers_raw()`, or this
|
||||||
|
/// will return NULL.
|
||||||
|
///
|
||||||
|
/// The returned `hyper_buf *` is just a reference, owned by the response.
|
||||||
|
/// You need to make a copy if you wish to use it after freeing the
|
||||||
|
/// response.
|
||||||
|
///
|
||||||
|
/// The buffer is not null-terminated, see the `hyper_buf` functions for
|
||||||
|
/// getting the bytes and length.
|
||||||
|
fn hyper_response_headers_raw(resp: *const hyper_response) -> *const hyper_buf {
|
||||||
|
match unsafe { &*resp }.0.extensions().get::<RawHeaders>() {
|
||||||
|
Some(raw) => &raw.0,
|
||||||
|
None => std::ptr::null(),
|
||||||
|
}
|
||||||
|
} ?= std::ptr::null()
|
||||||
|
}
|
||||||
|
|
||||||
ffi_fn! {
|
ffi_fn! {
|
||||||
/// Get the HTTP version used by this response.
|
/// Get the HTTP version used by this response.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -49,6 +49,8 @@ where
|
|||||||
preserve_header_case: false,
|
preserve_header_case: false,
|
||||||
title_case_headers: false,
|
title_case_headers: false,
|
||||||
h09_responses: false,
|
h09_responses: false,
|
||||||
|
#[cfg(feature = "ffi")]
|
||||||
|
raw_headers: false,
|
||||||
notify_read: false,
|
notify_read: false,
|
||||||
reading: Reading::Init,
|
reading: Reading::Init,
|
||||||
writing: Writing::Init,
|
writing: Writing::Init,
|
||||||
@@ -98,6 +100,11 @@ where
|
|||||||
self.state.allow_half_close = true;
|
self.state.allow_half_close = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ffi")]
|
||||||
|
pub(crate) fn set_raw_headers(&mut self, enabled: bool) {
|
||||||
|
self.state.raw_headers = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn into_inner(self) -> (I, Bytes) {
|
pub(crate) fn into_inner(self) -> (I, Bytes) {
|
||||||
self.io.into_inner()
|
self.io.into_inner()
|
||||||
}
|
}
|
||||||
@@ -162,6 +169,8 @@ where
|
|||||||
h1_parser_config: self.state.h1_parser_config.clone(),
|
h1_parser_config: self.state.h1_parser_config.clone(),
|
||||||
preserve_header_case: self.state.preserve_header_case,
|
preserve_header_case: self.state.preserve_header_case,
|
||||||
h09_responses: self.state.h09_responses,
|
h09_responses: self.state.h09_responses,
|
||||||
|
#[cfg(feature = "ffi")]
|
||||||
|
raw_headers: self.state.raw_headers,
|
||||||
}
|
}
|
||||||
)) {
|
)) {
|
||||||
Ok(msg) => msg,
|
Ok(msg) => msg,
|
||||||
@@ -766,6 +775,8 @@ struct State {
|
|||||||
preserve_header_case: bool,
|
preserve_header_case: bool,
|
||||||
title_case_headers: bool,
|
title_case_headers: bool,
|
||||||
h09_responses: bool,
|
h09_responses: bool,
|
||||||
|
#[cfg(feature = "ffi")]
|
||||||
|
raw_headers: bool,
|
||||||
/// Set to true when the Dispatcher should poll read operations
|
/// Set to true when the Dispatcher should poll read operations
|
||||||
/// again. See the `maybe_notify` method for more.
|
/// again. See the `maybe_notify` method for more.
|
||||||
notify_read: bool,
|
notify_read: bool,
|
||||||
|
|||||||
@@ -167,6 +167,8 @@ where
|
|||||||
h1_parser_config: parse_ctx.h1_parser_config.clone(),
|
h1_parser_config: parse_ctx.h1_parser_config.clone(),
|
||||||
preserve_header_case: parse_ctx.preserve_header_case,
|
preserve_header_case: parse_ctx.preserve_header_case,
|
||||||
h09_responses: parse_ctx.h09_responses,
|
h09_responses: parse_ctx.h09_responses,
|
||||||
|
#[cfg(feature = "ffi")]
|
||||||
|
raw_headers: parse_ctx.raw_headers,
|
||||||
},
|
},
|
||||||
)? {
|
)? {
|
||||||
Some(msg) => {
|
Some(msg) => {
|
||||||
@@ -675,6 +677,8 @@ mod tests {
|
|||||||
h1_parser_config: Default::default(),
|
h1_parser_config: Default::default(),
|
||||||
preserve_header_case: false,
|
preserve_header_case: false,
|
||||||
h09_responses: false,
|
h09_responses: false,
|
||||||
|
#[cfg(feature = "ffi")]
|
||||||
|
raw_headers: false,
|
||||||
};
|
};
|
||||||
assert!(buffered
|
assert!(buffered
|
||||||
.parse::<ClientTransaction>(cx, parse_ctx)
|
.parse::<ClientTransaction>(cx, parse_ctx)
|
||||||
|
|||||||
@@ -74,6 +74,8 @@ pub(crate) struct ParseContext<'a> {
|
|||||||
h1_parser_config: ParserConfig,
|
h1_parser_config: ParserConfig,
|
||||||
preserve_header_case: bool,
|
preserve_header_case: bool,
|
||||||
h09_responses: bool,
|
h09_responses: bool,
|
||||||
|
#[cfg(feature = "ffi")]
|
||||||
|
raw_headers: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Passed to Http1Transaction::encode
|
/// Passed to Http1Transaction::encode
|
||||||
|
|||||||
@@ -970,6 +970,11 @@ impl Http1Transaction for Client {
|
|||||||
#[cfg(not(feature = "ffi"))]
|
#[cfg(not(feature = "ffi"))]
|
||||||
drop(reason);
|
drop(reason);
|
||||||
|
|
||||||
|
#[cfg(feature = "ffi")]
|
||||||
|
if ctx.raw_headers {
|
||||||
|
extensions.insert(crate::ffi::RawHeaders(crate::ffi::hyper_buf(slice)));
|
||||||
|
}
|
||||||
|
|
||||||
let head = MessageHead {
|
let head = MessageHead {
|
||||||
version,
|
version,
|
||||||
subject: status,
|
subject: status,
|
||||||
@@ -1424,6 +1429,8 @@ mod tests {
|
|||||||
h1_parser_config: Default::default(),
|
h1_parser_config: Default::default(),
|
||||||
preserve_header_case: false,
|
preserve_header_case: false,
|
||||||
h09_responses: false,
|
h09_responses: false,
|
||||||
|
#[cfg(feature = "ffi")]
|
||||||
|
raw_headers: false,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@@ -1447,6 +1454,8 @@ mod tests {
|
|||||||
h1_parser_config: Default::default(),
|
h1_parser_config: Default::default(),
|
||||||
preserve_header_case: false,
|
preserve_header_case: false,
|
||||||
h09_responses: false,
|
h09_responses: false,
|
||||||
|
#[cfg(feature = "ffi")]
|
||||||
|
raw_headers: false,
|
||||||
};
|
};
|
||||||
let msg = Client::parse(&mut raw, ctx).unwrap().unwrap();
|
let msg = Client::parse(&mut raw, ctx).unwrap().unwrap();
|
||||||
assert_eq!(raw.len(), 0);
|
assert_eq!(raw.len(), 0);
|
||||||
@@ -1465,6 +1474,8 @@ mod tests {
|
|||||||
h1_parser_config: Default::default(),
|
h1_parser_config: Default::default(),
|
||||||
preserve_header_case: false,
|
preserve_header_case: false,
|
||||||
h09_responses: false,
|
h09_responses: false,
|
||||||
|
#[cfg(feature = "ffi")]
|
||||||
|
raw_headers: false,
|
||||||
};
|
};
|
||||||
Server::parse(&mut raw, ctx).unwrap_err();
|
Server::parse(&mut raw, ctx).unwrap_err();
|
||||||
}
|
}
|
||||||
@@ -1481,6 +1492,8 @@ mod tests {
|
|||||||
h1_parser_config: Default::default(),
|
h1_parser_config: Default::default(),
|
||||||
preserve_header_case: false,
|
preserve_header_case: false,
|
||||||
h09_responses: true,
|
h09_responses: true,
|
||||||
|
#[cfg(feature = "ffi")]
|
||||||
|
raw_headers: false,
|
||||||
};
|
};
|
||||||
let msg = Client::parse(&mut raw, ctx).unwrap().unwrap();
|
let msg = Client::parse(&mut raw, ctx).unwrap().unwrap();
|
||||||
assert_eq!(raw, H09_RESPONSE);
|
assert_eq!(raw, H09_RESPONSE);
|
||||||
@@ -1499,6 +1512,8 @@ mod tests {
|
|||||||
h1_parser_config: Default::default(),
|
h1_parser_config: Default::default(),
|
||||||
preserve_header_case: false,
|
preserve_header_case: false,
|
||||||
h09_responses: false,
|
h09_responses: false,
|
||||||
|
#[cfg(feature = "ffi")]
|
||||||
|
raw_headers: false,
|
||||||
};
|
};
|
||||||
Client::parse(&mut raw, ctx).unwrap_err();
|
Client::parse(&mut raw, ctx).unwrap_err();
|
||||||
assert_eq!(raw, H09_RESPONSE);
|
assert_eq!(raw, H09_RESPONSE);
|
||||||
@@ -1521,6 +1536,8 @@ mod tests {
|
|||||||
h1_parser_config,
|
h1_parser_config,
|
||||||
preserve_header_case: false,
|
preserve_header_case: false,
|
||||||
h09_responses: false,
|
h09_responses: false,
|
||||||
|
#[cfg(feature = "ffi")]
|
||||||
|
raw_headers: false,
|
||||||
};
|
};
|
||||||
let msg = Client::parse(&mut raw, ctx).unwrap().unwrap();
|
let msg = Client::parse(&mut raw, ctx).unwrap().unwrap();
|
||||||
assert_eq!(raw.len(), 0);
|
assert_eq!(raw.len(), 0);
|
||||||
@@ -1540,6 +1557,8 @@ mod tests {
|
|||||||
h1_parser_config: Default::default(),
|
h1_parser_config: Default::default(),
|
||||||
preserve_header_case: false,
|
preserve_header_case: false,
|
||||||
h09_responses: false,
|
h09_responses: false,
|
||||||
|
#[cfg(feature = "ffi")]
|
||||||
|
raw_headers: false,
|
||||||
};
|
};
|
||||||
Client::parse(&mut raw, ctx).unwrap_err();
|
Client::parse(&mut raw, ctx).unwrap_err();
|
||||||
}
|
}
|
||||||
@@ -1554,6 +1573,8 @@ mod tests {
|
|||||||
h1_parser_config: Default::default(),
|
h1_parser_config: Default::default(),
|
||||||
preserve_header_case: true,
|
preserve_header_case: true,
|
||||||
h09_responses: false,
|
h09_responses: false,
|
||||||
|
#[cfg(feature = "ffi")]
|
||||||
|
raw_headers: false,
|
||||||
};
|
};
|
||||||
let parsed_message = Server::parse(&mut raw, ctx).unwrap().unwrap();
|
let parsed_message = Server::parse(&mut raw, ctx).unwrap().unwrap();
|
||||||
let orig_headers = parsed_message
|
let orig_headers = parsed_message
|
||||||
@@ -1589,6 +1610,8 @@ mod tests {
|
|||||||
h1_parser_config: Default::default(),
|
h1_parser_config: Default::default(),
|
||||||
preserve_header_case: false,
|
preserve_header_case: false,
|
||||||
h09_responses: false,
|
h09_responses: false,
|
||||||
|
#[cfg(feature = "ffi")]
|
||||||
|
raw_headers: false,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.expect("parse ok")
|
.expect("parse ok")
|
||||||
@@ -1605,6 +1628,8 @@ mod tests {
|
|||||||
h1_parser_config: Default::default(),
|
h1_parser_config: Default::default(),
|
||||||
preserve_header_case: false,
|
preserve_header_case: false,
|
||||||
h09_responses: false,
|
h09_responses: false,
|
||||||
|
#[cfg(feature = "ffi")]
|
||||||
|
raw_headers: false,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.expect_err(comment)
|
.expect_err(comment)
|
||||||
@@ -1820,6 +1845,8 @@ mod tests {
|
|||||||
h1_parser_config: Default::default(),
|
h1_parser_config: Default::default(),
|
||||||
preserve_header_case: false,
|
preserve_header_case: false,
|
||||||
h09_responses: false,
|
h09_responses: false,
|
||||||
|
#[cfg(feature = "ffi")]
|
||||||
|
raw_headers: false,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.expect("parse ok")
|
.expect("parse ok")
|
||||||
@@ -1836,6 +1863,8 @@ mod tests {
|
|||||||
h1_parser_config: Default::default(),
|
h1_parser_config: Default::default(),
|
||||||
preserve_header_case: false,
|
preserve_header_case: false,
|
||||||
h09_responses: false,
|
h09_responses: false,
|
||||||
|
#[cfg(feature = "ffi")]
|
||||||
|
raw_headers: false,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.expect("parse ok")
|
.expect("parse ok")
|
||||||
@@ -1852,6 +1881,8 @@ mod tests {
|
|||||||
h1_parser_config: Default::default(),
|
h1_parser_config: Default::default(),
|
||||||
preserve_header_case: false,
|
preserve_header_case: false,
|
||||||
h09_responses: false,
|
h09_responses: false,
|
||||||
|
#[cfg(feature = "ffi")]
|
||||||
|
raw_headers: false,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.expect_err("parse should err")
|
.expect_err("parse should err")
|
||||||
@@ -2335,6 +2366,8 @@ mod tests {
|
|||||||
h1_parser_config: Default::default(),
|
h1_parser_config: Default::default(),
|
||||||
preserve_header_case: false,
|
preserve_header_case: false,
|
||||||
h09_responses: false,
|
h09_responses: false,
|
||||||
|
#[cfg(feature = "ffi")]
|
||||||
|
raw_headers: false,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.expect("parse ok")
|
.expect("parse ok")
|
||||||
@@ -2415,6 +2448,8 @@ mod tests {
|
|||||||
h1_parser_config: Default::default(),
|
h1_parser_config: Default::default(),
|
||||||
preserve_header_case: false,
|
preserve_header_case: false,
|
||||||
h09_responses: false,
|
h09_responses: false,
|
||||||
|
#[cfg(feature = "ffi")]
|
||||||
|
raw_headers: false,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@@ -2451,6 +2486,8 @@ mod tests {
|
|||||||
h1_parser_config: Default::default(),
|
h1_parser_config: Default::default(),
|
||||||
preserve_header_case: false,
|
preserve_header_case: false,
|
||||||
h09_responses: false,
|
h09_responses: false,
|
||||||
|
#[cfg(feature = "ffi")]
|
||||||
|
raw_headers: false,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|||||||
Reference in New Issue
Block a user