mirror of https://github.com/fafhrd91/actix-web
refactor: remove Option from RequestHeadType::Rc extra headers
Replace `RequestHeadType::Rc(Rc<RequestHead>, Option<HeaderMap>)` with `RequestHeadType::Rc(Rc<RequestHead>, HeaderMap)`, using an empty HeaderMap as the default instead of None. This enables: - `RequestHeadType::extra_headers_mut()` for modifying headers on both Owned and Rc variants - `ConnectRequest::headers_mut()` for middleware to insert headers without destructuring the request Closes #2477
This commit is contained in:
parent
7ded7ee478
commit
0160b00a90
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
- Remove `Option` wrapper from `RequestHeadType::Rc` extra headers; add `RequestHeadType::extra_headers_mut()` method.
|
||||||
- When configured, gracefully close HTTP/1 connections after early responses to unread request bodies. [#3967]
|
- When configured, gracefully close HTTP/1 connections after early responses to unread request bodies. [#3967]
|
||||||
- Wake HTTP/1 payload receivers with an incomplete-payload error when the sender is dropped before EOF. [#3100]
|
- Wake HTTP/1 payload receivers with an incomplete-payload error when the sender is dropped before EOF. [#3100]
|
||||||
- Update `foldhash` dependency to `0.2`.
|
- Update `foldhash` dependency to `0.2`.
|
||||||
|
|
|
||||||
|
|
@ -648,7 +648,7 @@ mod tests {
|
||||||
);
|
);
|
||||||
extra_headers.insert(DATE, HeaderValue::from_static("date"));
|
extra_headers.insert(DATE, HeaderValue::from_static("date"));
|
||||||
|
|
||||||
let mut head = RequestHeadType::Rc(Rc::new(head), Some(extra_headers));
|
let mut head = RequestHeadType::Rc(Rc::new(head), extra_headers);
|
||||||
|
|
||||||
let _ = head.encode_headers(
|
let _ = head.encode_headers(
|
||||||
&mut bytes,
|
&mut bytes,
|
||||||
|
|
|
||||||
|
|
@ -150,14 +150,32 @@ impl RequestHead {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum RequestHeadType {
|
pub enum RequestHeadType {
|
||||||
Owned(RequestHead),
|
Owned(RequestHead),
|
||||||
Rc(Rc<RequestHead>, Option<HeaderMap>),
|
Rc(Rc<RequestHead>, HeaderMap),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RequestHeadType {
|
impl RequestHeadType {
|
||||||
pub fn extra_headers(&self) -> Option<&HeaderMap> {
|
pub fn extra_headers(&self) -> Option<&HeaderMap> {
|
||||||
match self {
|
match self {
|
||||||
RequestHeadType::Owned(_) => None,
|
RequestHeadType::Owned(_) => None,
|
||||||
RequestHeadType::Rc(_, headers) => headers.as_ref(),
|
RequestHeadType::Rc(_, headers) => {
|
||||||
|
if headers.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(headers)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a mutable reference to the headers that can be modified on this request.
|
||||||
|
///
|
||||||
|
/// For `Owned` variants, this returns the main header map.
|
||||||
|
/// For `Rc` variants, this returns the extra headers map (which overrides base headers
|
||||||
|
/// during encoding).
|
||||||
|
pub fn extra_headers_mut(&mut self) -> &mut HeaderMap {
|
||||||
|
match self {
|
||||||
|
RequestHeadType::Owned(head) => &mut head.headers,
|
||||||
|
RequestHeadType::Rc(_, headers) => headers,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
- Add `ConnectRequest::headers_mut()` to allow middleware to modify request headers.
|
||||||
- Add camel-case header controls to `WebsocketsRequest` via `camel_case_headers()` and `set_camel_case_headers()`. [#3953]
|
- Add camel-case header controls to `WebsocketsRequest` via `camel_case_headers()` and `set_camel_case_headers()`. [#3953]
|
||||||
- Update `hickory-resolver` dependency to `0.26.1`.
|
- Update `hickory-resolver` dependency to `0.26.1`.
|
||||||
- Update `rand` dependency to `0.10`.
|
- Update `rand` dependency to `0.10`.
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ use actix_http::{
|
||||||
body::{BodySize, MessageBody},
|
body::{BodySize, MessageBody},
|
||||||
error::PayloadError,
|
error::PayloadError,
|
||||||
h1,
|
h1,
|
||||||
header::{HeaderMap, TryIntoHeaderValue, EXPECT, HOST},
|
header::{TryIntoHeaderValue, EXPECT, HOST},
|
||||||
Payload, RequestHeadType, ResponseHead, StatusCode,
|
Payload, RequestHeadType, ResponseHead, StatusCode,
|
||||||
};
|
};
|
||||||
use actix_utils::future::poll_fn;
|
use actix_utils::future::poll_fn;
|
||||||
|
|
@ -76,15 +76,9 @@ where
|
||||||
};
|
};
|
||||||
|
|
||||||
match wrt.get_mut().split().freeze().try_into_value() {
|
match wrt.get_mut().split().freeze().try_into_value() {
|
||||||
Ok(value) => match head {
|
Ok(value) => {
|
||||||
RequestHeadType::Owned(ref mut head) => {
|
head.extra_headers_mut().insert(HOST, value);
|
||||||
head.headers.insert(HOST, value);
|
}
|
||||||
}
|
|
||||||
RequestHeadType::Rc(_, ref mut extra_headers) => {
|
|
||||||
let headers = extra_headers.get_or_insert(HeaderMap::new());
|
|
||||||
headers.insert(HOST, value);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Err(err) => log::error!("Can not set HOST header {err}"),
|
Err(err) => log::error!("Can not set HOST header {err}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -77,10 +77,9 @@ where
|
||||||
// Extracting extra headers from RequestHeadType. HeaderMap::new() does not allocate.
|
// Extracting extra headers from RequestHeadType. HeaderMap::new() does not allocate.
|
||||||
let (head, extra_headers) = match head {
|
let (head, extra_headers) = match head {
|
||||||
RequestHeadType::Owned(head) => (RequestHeadType::Owned(head), HeaderMap::new()),
|
RequestHeadType::Owned(head) => (RequestHeadType::Owned(head), HeaderMap::new()),
|
||||||
RequestHeadType::Rc(head, extra_headers) => (
|
RequestHeadType::Rc(head, extra_headers) => {
|
||||||
RequestHeadType::Rc(head, None),
|
(RequestHeadType::Rc(head, HeaderMap::new()), extra_headers)
|
||||||
extra_headers.unwrap_or_else(HeaderMap::new),
|
}
|
||||||
),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// merging headers from head and extra headers.
|
// merging headers from head and extra headers.
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,19 @@ pub enum ConnectRequest {
|
||||||
Tunnel(RequestHead, Option<net::SocketAddr>),
|
Tunnel(RequestHead, Option<net::SocketAddr>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ConnectRequest {
|
||||||
|
/// Returns a mutable reference to the request headers.
|
||||||
|
///
|
||||||
|
/// For `Client` requests using the `Rc` variant, this returns the extra headers map
|
||||||
|
/// (which takes priority over base headers during encoding).
|
||||||
|
pub fn headers_mut(&mut self) -> &mut actix_http::header::HeaderMap {
|
||||||
|
match self {
|
||||||
|
ConnectRequest::Client(head, ..) => head.extra_headers_mut(),
|
||||||
|
ConnectRequest::Tunnel(head, ..) => &mut head.headers,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Combined HTTP response & WebSocket tunnel type returned from connection service.
|
/// Combined HTTP response & WebSocket tunnel type returned from connection service.
|
||||||
pub enum ConnectResponse {
|
pub enum ConnectResponse {
|
||||||
/// Standard HTTP response.
|
/// Standard HTTP response.
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ impl FrozenClientRequest {
|
||||||
where
|
where
|
||||||
B: MessageBody + 'static,
|
B: MessageBody + 'static,
|
||||||
{
|
{
|
||||||
RequestSender::Rc(Rc::clone(&self.head), None).send_body(
|
RequestSender::Rc(Rc::clone(&self.head), HeaderMap::new()).send_body(
|
||||||
self.addr,
|
self.addr,
|
||||||
self.response_decompress,
|
self.response_decompress,
|
||||||
self.timeout,
|
self.timeout,
|
||||||
|
|
@ -60,7 +60,7 @@ impl FrozenClientRequest {
|
||||||
|
|
||||||
/// Send a json body.
|
/// Send a json body.
|
||||||
pub fn send_json<T: Serialize>(&self, value: &T) -> SendClientRequest {
|
pub fn send_json<T: Serialize>(&self, value: &T) -> SendClientRequest {
|
||||||
RequestSender::Rc(Rc::clone(&self.head), None).send_json(
|
RequestSender::Rc(Rc::clone(&self.head), HeaderMap::new()).send_json(
|
||||||
self.addr,
|
self.addr,
|
||||||
self.response_decompress,
|
self.response_decompress,
|
||||||
self.timeout,
|
self.timeout,
|
||||||
|
|
@ -71,7 +71,7 @@ impl FrozenClientRequest {
|
||||||
|
|
||||||
/// Send an urlencoded body.
|
/// Send an urlencoded body.
|
||||||
pub fn send_form<T: Serialize>(&self, value: &T) -> SendClientRequest {
|
pub fn send_form<T: Serialize>(&self, value: &T) -> SendClientRequest {
|
||||||
RequestSender::Rc(Rc::clone(&self.head), None).send_form(
|
RequestSender::Rc(Rc::clone(&self.head), HeaderMap::new()).send_form(
|
||||||
self.addr,
|
self.addr,
|
||||||
self.response_decompress,
|
self.response_decompress,
|
||||||
self.timeout,
|
self.timeout,
|
||||||
|
|
@ -86,7 +86,7 @@ impl FrozenClientRequest {
|
||||||
S: Stream<Item = Result<Bytes, E>> + 'static,
|
S: Stream<Item = Result<Bytes, E>> + 'static,
|
||||||
E: Into<BoxError> + 'static,
|
E: Into<BoxError> + 'static,
|
||||||
{
|
{
|
||||||
RequestSender::Rc(Rc::clone(&self.head), None).send_stream(
|
RequestSender::Rc(Rc::clone(&self.head), HeaderMap::new()).send_stream(
|
||||||
self.addr,
|
self.addr,
|
||||||
self.response_decompress,
|
self.response_decompress,
|
||||||
self.timeout,
|
self.timeout,
|
||||||
|
|
@ -97,7 +97,7 @@ impl FrozenClientRequest {
|
||||||
|
|
||||||
/// Send an empty body.
|
/// Send an empty body.
|
||||||
pub fn send(&self) -> SendClientRequest {
|
pub fn send(&self) -> SendClientRequest {
|
||||||
RequestSender::Rc(Rc::clone(&self.head), None).send(
|
RequestSender::Rc(Rc::clone(&self.head), HeaderMap::new()).send(
|
||||||
self.addr,
|
self.addr,
|
||||||
self.response_decompress,
|
self.response_decompress,
|
||||||
self.timeout,
|
self.timeout,
|
||||||
|
|
@ -151,7 +151,7 @@ impl FrozenSendBuilder {
|
||||||
return err.into();
|
return err.into();
|
||||||
}
|
}
|
||||||
|
|
||||||
RequestSender::Rc(self.req.head, Some(self.extra_headers)).send_body(
|
RequestSender::Rc(self.req.head, self.extra_headers).send_body(
|
||||||
self.req.addr,
|
self.req.addr,
|
||||||
self.req.response_decompress,
|
self.req.response_decompress,
|
||||||
self.req.timeout,
|
self.req.timeout,
|
||||||
|
|
@ -166,7 +166,7 @@ impl FrozenSendBuilder {
|
||||||
return err.into();
|
return err.into();
|
||||||
}
|
}
|
||||||
|
|
||||||
RequestSender::Rc(self.req.head, Some(self.extra_headers)).send_json(
|
RequestSender::Rc(self.req.head, self.extra_headers).send_json(
|
||||||
self.req.addr,
|
self.req.addr,
|
||||||
self.req.response_decompress,
|
self.req.response_decompress,
|
||||||
self.req.timeout,
|
self.req.timeout,
|
||||||
|
|
@ -181,7 +181,7 @@ impl FrozenSendBuilder {
|
||||||
return err.into();
|
return err.into();
|
||||||
}
|
}
|
||||||
|
|
||||||
RequestSender::Rc(self.req.head, Some(self.extra_headers)).send_form(
|
RequestSender::Rc(self.req.head, self.extra_headers).send_form(
|
||||||
self.req.addr,
|
self.req.addr,
|
||||||
self.req.response_decompress,
|
self.req.response_decompress,
|
||||||
self.req.timeout,
|
self.req.timeout,
|
||||||
|
|
@ -200,7 +200,7 @@ impl FrozenSendBuilder {
|
||||||
return err.into();
|
return err.into();
|
||||||
}
|
}
|
||||||
|
|
||||||
RequestSender::Rc(self.req.head, Some(self.extra_headers)).send_stream(
|
RequestSender::Rc(self.req.head, self.extra_headers).send_stream(
|
||||||
self.req.addr,
|
self.req.addr,
|
||||||
self.req.response_decompress,
|
self.req.response_decompress,
|
||||||
self.req.timeout,
|
self.req.timeout,
|
||||||
|
|
@ -215,7 +215,7 @@ impl FrozenSendBuilder {
|
||||||
return err.into();
|
return err.into();
|
||||||
}
|
}
|
||||||
|
|
||||||
RequestSender::Rc(self.req.head, Some(self.extra_headers)).send(
|
RequestSender::Rc(self.req.head, self.extra_headers).send(
|
||||||
self.req.addr,
|
self.req.addr,
|
||||||
self.req.response_decompress,
|
self.req.response_decompress,
|
||||||
self.req.timeout,
|
self.req.timeout,
|
||||||
|
|
|
||||||
|
|
@ -176,7 +176,7 @@ impl From<PrepForSendingError> for SendClientRequest {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) enum RequestSender {
|
pub(crate) enum RequestSender {
|
||||||
Owned(RequestHead),
|
Owned(RequestHead),
|
||||||
Rc(Rc<RequestHead>, Option<HeaderMap>),
|
Rc(Rc<RequestHead>, HeaderMap),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RequestSender {
|
impl RequestSender {
|
||||||
|
|
@ -296,14 +296,9 @@ impl RequestSender {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RequestSender::Rc(head, extra_headers) => {
|
RequestSender::Rc(head, extra_headers) => {
|
||||||
if !head.headers.contains_key(&key)
|
if !head.headers.contains_key(&key) && !extra_headers.contains_key(&key) {
|
||||||
&& !extra_headers.iter().any(|h| h.contains_key(&key))
|
|
||||||
{
|
|
||||||
match value.try_into_value() {
|
match value.try_into_value() {
|
||||||
Ok(v) => {
|
Ok(v) => extra_headers.insert(key, v),
|
||||||
let h = extra_headers.get_or_insert(HeaderMap::new());
|
|
||||||
h.insert(key, v)
|
|
||||||
}
|
|
||||||
Err(err) => return Err(err.into()),
|
Err(err) => return Err(err.into()),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue