use {
crate::{
body::Body, downstream::DownstreamResponse, error::Error, handoff::HandoffInfo,
sandbox::async_item::PendingResponse,
},
hyper::http::response::Response,
tokio::sync::mpsc::Sender,
};
pub enum DownstreamResponseState {
Unsent(Sender<DownstreamResponse>),
HandingOffToPushpin,
HandingOffToBackend,
Sent,
}
impl DownstreamResponseState {
pub fn new(sender: Sender<DownstreamResponse>) -> Self {
DownstreamResponseState::Unsent(sender)
}
pub fn is_unsent(&self) -> bool {
matches!(self, Self::Unsent(_))
}
pub async fn send(&mut self, response: Response<Body>) -> Result<(), Error> {
let Self::Unsent(sender) = self else {
return Err(Error::DownstreamRespSending);
};
if response.status().as_u16() == 103 {
let _ = sender.send(DownstreamResponse::Http(response)).await;
return Ok(());
} else if response.status().is_informational() {
return Err(Error::InvalidArgument);
}
sender
.send(DownstreamResponse::Http(response))
.await
.map_err(|_| ())
.expect("response receiver is open");
*self = Self::Sent;
Ok(())
}
pub fn send_close(&mut self, response: Response<Body>) {
let Self::Unsent(sender) = self else {
return;
};
let _ = sender.try_send(DownstreamResponse::Http(response));
*self = Self::Sent;
}
pub async fn send_pending(&mut self, pending: PendingResponse) -> Result<(), Error> {
let Self::Unsent(sender) = self else {
return Err(Error::DownstreamRespSending);
};
sender
.send(DownstreamResponse::Pending(pending.into()))
.await
.map_err(|_| ())
.expect("response receiver is open");
*self = Self::Sent;
Ok(())
}
pub async fn redirect_to_pushpin(&mut self, redirect_info: HandoffInfo) -> Result<(), Error> {
let Self::Unsent(sender) = self else {
return Err(Error::DownstreamRespSending);
};
sender
.send(DownstreamResponse::HandoffToPushpin(redirect_info))
.await
.map_err(|_| ())
.expect("response receiver is open");
*self = Self::HandingOffToPushpin;
Ok(())
}
pub async fn redirect_to_backend(&mut self, redirect_info: HandoffInfo) -> Result<(), Error> {
let Self::Unsent(sender) = self else {
return Err(Error::DownstreamRespSending);
};
sender
.send(DownstreamResponse::HandoffToBackend(redirect_info))
.await
.map_err(|_| ())
.expect("response receiver is open");
*self = Self::HandingOffToBackend;
Ok(())
}
}