use crate::{
Conn, HttpConfig, Result, TypeSet, Upgrade, h1::H1Connection,
headers::header_observer::HeaderObserver,
};
use fieldwork::Fieldwork;
use futures_lite::{AsyncRead, AsyncWrite};
use std::{future::Future, sync::Arc};
use swansong::{ShutdownCompletion, Swansong};
pub(crate) type ConnectionContext = Arc<Arc<HttpContext>>;
#[derive(Default, Debug, Fieldwork)]
#[fieldwork(get, set, get_mut, with)]
pub struct HttpContext {
pub(crate) config: HttpConfig,
pub(crate) swansong: Swansong,
pub(crate) shared_state: TypeSet,
#[cfg_attr(not(feature = "unstable"), field = false)]
pub(crate) observer: Arc<HeaderObserver>,
}
impl AsRef<TypeSet> for HttpContext {
fn as_ref(&self) -> &TypeSet {
&self.shared_state
}
}
impl AsMut<TypeSet> for HttpContext {
fn as_mut(&mut self) -> &mut TypeSet {
&mut self.shared_state
}
}
impl AsRef<Swansong> for HttpContext {
fn as_ref(&self) -> &Swansong {
&self.swansong
}
}
impl AsRef<HttpConfig> for HttpContext {
fn as_ref(&self) -> &HttpConfig {
&self.config
}
}
impl HttpContext {
pub fn new() -> Self {
Self::default()
}
pub async fn run<Transport, Handler, Fut>(
self: Arc<Self>,
transport: Transport,
handler: Handler,
) -> Result<Option<Upgrade<Transport>>>
where
Transport: AsyncRead + AsyncWrite + Unpin + Send + Sync + 'static,
Handler: FnMut(Conn<Transport>) -> Fut,
Fut: Future<Output = Conn<Transport>>,
{
H1Connection::new(self, transport)
.run(handler)
.await
.into_upgrade()
}
pub fn shut_down(&self) -> ShutdownCompletion {
self.swansong.shut_down()
}
#[doc(hidden)]
pub fn __isolate_header_observer(&mut self) -> &mut Self {
self.observer = Arc::new(HeaderObserver::default());
self
}
}
#[deprecated(
since = "1.8.0",
note = "use `H1Connection::new(context, \
transport).with_initial_bytes(initial_bytes).run(handler)`"
)]
pub async fn run_with_initial_bytes<Transport, Handler, Fut>(
context: Arc<HttpContext>,
transport: Transport,
initial_bytes: Vec<u8>,
handler: Handler,
) -> Result<Option<Upgrade<Transport>>>
where
Transport: AsyncRead + AsyncWrite + Unpin + Send + Sync + 'static,
Handler: FnMut(Conn<Transport>) -> Fut,
Fut: Future<Output = Conn<Transport>>,
{
H1Connection::new(context, transport)
.with_initial_bytes(initial_bytes)
.run(handler)
.await
.into_upgrade()
}
#[cfg(feature = "unstable")]
#[doc(hidden)]
pub async fn parse_head_for_bench<Transport>(
context: Arc<HttpContext>,
transport: Transport,
) -> Result<Conn<Transport>>
where
Transport: AsyncRead + AsyncWrite + Unpin + Send + Sync + 'static,
{
let initial_bytes = Vec::with_capacity(context.config.request_buffer_initial_len);
match Conn::new_h1(context, transport, initial_bytes).await {
Ok(conn) => Ok(conn),
Err(crate::conn::HeadError::BadRequest(bad)) => Ok(bad),
Err(crate::conn::HeadError::Fatal(e)) => Err(e),
}
}