wip: manipulate response header

This commit is contained in:
Jun Kurihara 2023-11-28 16:56:23 +09:00
commit f0b0dbc252
No known key found for this signature in database
GPG key ID: D992B3E3DE1DED23
4 changed files with 57 additions and 54 deletions

View file

@ -10,4 +10,4 @@ pub(crate) use self::{
upstream::{PathManager, Upstream, UpstreamCandidates},
upstream_opts::UpstreamOption,
};
pub(crate) use backend_main::{BackendAppBuilderError, BackendAppManager};
pub(crate) use backend_main::{BackendApp, BackendAppBuilderError, BackendAppManager};

View file

@ -38,7 +38,7 @@ where
U: CryptoSource + Clone,
{
// forwarder: Arc<Forwarder<T>>,
globals: Arc<Globals>,
pub(super) globals: Arc<Globals>,
app_manager: Arc<BackendAppManager<U>>,
}
@ -155,7 +155,7 @@ where
tls_enabled,
) {
Err(e) => {
error!("Failed to generate destination uri for backend application: {}", e);
error!("Failed to generate upstream request for backend application: {}", e);
return Err(HttpError::FailedToGenerateUpstreamRequest(e.to_string()));
}
Ok(v) => v,
@ -199,12 +199,12 @@ where
}
if res_backend.status() != StatusCode::SWITCHING_PROTOCOLS {
// // Generate response to client
// if self.generate_response_forwarded(&mut res_backend, backend).is_err() {
// return self.return_with_error_log(StatusCode::INTERNAL_SERVER_ERROR, &mut log_data);
// }
// log_data.status_code(&res_backend.status()).output();
// return Ok(res_backend);
// Generate response to client
if let Err(e) = self.generate_response_forwarded(&mut res_backend, backend_app) {
error!("Failed to generate downstream response for clients: {}", e);
return Err(HttpError::FailedToGenerateDownstreamResponse(e.to_string()));
}
return Ok(res_backend);
}
// // Handle StatusCode::SWITCHING_PROTOCOLS in response

View file

@ -2,9 +2,14 @@ use super::{
handler_main::HandlerContext, utils_headers::*, utils_request::apply_upstream_options_to_request_line,
HttpMessageHandler,
};
use crate::{backend::UpstreamCandidates, log::*, CryptoSource};
use crate::{
backend::{BackendApp, UpstreamCandidates},
constants::RESPONSE_HEADER_SERVER,
log::*,
CryptoSource,
};
use anyhow::{anyhow, ensure, Result};
use http::{header, uri::Scheme, HeaderValue, Request, Uri, Version};
use http::{header, uri::Scheme, HeaderValue, Request, Response, Uri, Version};
use std::net::SocketAddr;
impl<U> HttpMessageHandler<U>
@ -15,51 +20,46 @@ where
// Functions to generate messages
////////////////////////////////////////////////////
// /// Manipulate a response message sent from a backend application to forward downstream to a client.
// fn generate_response_forwarded<B>(&self, response: &mut Response<B>, chosen_backend: &Backend<U>) -> Result<()> {
// where
// B: core::fmt::Debug,
// {
// let headers = response.headers_mut();
// remove_connection_header(headers);
// remove_hop_header(headers);
// add_header_entry_overwrite_if_exist(headers, "server", RESPONSE_HEADER_SERVER)?;
/// Manipulate a response message sent from a backend application to forward downstream to a client.
pub(super) fn generate_response_forwarded<B>(
&self,
response: &mut Response<B>,
backend_app: &BackendApp<U>,
) -> Result<()> {
let headers = response.headers_mut();
remove_connection_header(headers);
remove_hop_header(headers);
add_header_entry_overwrite_if_exist(headers, "server", RESPONSE_HEADER_SERVER)?;
// #[cfg(any(feature = "http3-quinn", feature = "http3-s2n"))]
// {
// // Manipulate ALT_SVC allowing h3 in response message only when mutual TLS is not enabled
// // TODO: This is a workaround for avoiding a client authentication in HTTP/3
// if self.globals.proxy_config.http3
// && chosen_backend
// .crypto_source
// .as_ref()
// .is_some_and(|v| !v.is_mutual_tls())
// {
// if let Some(port) = self.globals.proxy_config.https_port {
// add_header_entry_overwrite_if_exist(
// headers,
// header::ALT_SVC.as_str(),
// format!(
// "h3=\":{}\"; ma={}, h3-29=\":{}\"; ma={}",
// port, self.globals.proxy_config.h3_alt_svc_max_age, port, self.globals.proxy_config.h3_alt_svc_max_age
// ),
// )?;
// }
// } else {
// // remove alt-svc to disallow requests via http3
// headers.remove(header::ALT_SVC.as_str());
// }
// }
// #[cfg(not(any(feature = "http3-quinn", feature = "http3-s2n")))]
// {
// if let Some(port) = self.globals.proxy_config.https_port {
// headers.remove(header::ALT_SVC.as_str());
// }
// }
#[cfg(any(feature = "http3-quinn", feature = "http3-s2n"))]
{
// Manipulate ALT_SVC allowing h3 in response message only when mutual TLS is not enabled
// TODO: This is a workaround for avoiding a client authentication in HTTP/3
if self.globals.proxy_config.http3 && backend_app.crypto_source.as_ref().is_some_and(|v| !v.is_mutual_tls()) {
if let Some(port) = self.globals.proxy_config.https_port {
add_header_entry_overwrite_if_exist(
headers,
header::ALT_SVC.as_str(),
format!(
"h3=\":{}\"; ma={}, h3-29=\":{}\"; ma={}",
port, self.globals.proxy_config.h3_alt_svc_max_age, port, self.globals.proxy_config.h3_alt_svc_max_age
),
)?;
}
} else {
// remove alt-svc to disallow requests via http3
headers.remove(header::ALT_SVC.as_str());
}
}
#[cfg(not(any(feature = "http3-quinn", feature = "http3-s2n")))]
{
if self.globals.proxy_config.https_port.is_some() {
headers.remove(header::ALT_SVC.as_str());
}
}
// Ok(())
// todo!()
// }
Ok(())
}
#[allow(clippy::too_many_arguments)]
/// Manipulate a request message sent from a client to forward upstream to a backend application

View file

@ -25,6 +25,8 @@ pub enum HttpError {
#[error("Failed to add set-cookie header in response")]
FailedToAddSetCookeInResponse,
#[error("Failed to generated downstream response: {0}")]
FailedToGenerateDownstreamResponse(String),
#[error(transparent)]
Other(#[from] anyhow::Error),
@ -41,6 +43,7 @@ impl From<HttpError> for StatusCode {
HttpError::NoUpstreamCandidates => StatusCode::NOT_FOUND,
HttpError::FailedToGenerateUpstreamRequest(_) => StatusCode::INTERNAL_SERVER_ERROR,
HttpError::FailedToAddSetCookeInResponse => StatusCode::INTERNAL_SERVER_ERROR,
HttpError::FailedToGenerateDownstreamResponse(_) => StatusCode::INTERNAL_SERVER_ERROR,
_ => StatusCode::INTERNAL_SERVER_ERROR,
}
}