use std::ops;
use std::sync::Arc;
use super::{HttpRequest, HttpResponse};
#[async_trait::async_trait]
pub trait HttpContextInterface: Send + Sync {
type State;
async fn new(
extensions: &super::Extensions,
state: Self::State,
) -> Option<Self>
where
Self: Sized;
fn shared(self) -> Arc<Self>
where
Self: Sized,
{
Arc::new(self)
}
}
pub struct HttpContext<T> {
pub(crate) context: Arc<T>,
pub request: HttpRequest<T>,
pub response: HttpResponse<T>,
#[cfg(feature = "cookies")]
pub cookies: super::cookies::Cookies,
#[cfg(feature = "cookies")]
pub session: super::session::Session,
}
impl<T> HttpContext<T> {
pub fn redirect_back(&self) -> axum::response::Redirect {
assert!(self.request.referer.is_some());
let referer = self.request.referer.as_ref().expect("Referer");
fn referer_url(referer: &axum::headers::Referer) -> String {
let referer_s = format!("{referer:?}");
let trimmed_referer = referer_s
.trim_start_matches("Referer(\"")
.trim_end_matches("\")");
trimmed_referer.to_owned()
}
let uri = referer_url(referer);
self.response.redirect_to(uri)
}
}
#[cfg(feature = "auth")]
impl<T> HttpContext<T> {
pub async fn logout_user(&mut self) {
let mut session = self.session.write().await;
session.remove(crate::auth::AUTH_USER_ID_SESSION);
session.remove(crate::auth::AUTH_ADMIN_ID_SESSION);
session.regenerate();
if let Some(mut user_cookie) = self
.cookies
.private()
.get(crate::auth::AUTH_USER_ID_SESSION)
{
let expires_in = time::OffsetDateTime::now_utc()
.checked_sub(time::Duration::days(100));
user_cookie.set_path("/");
user_cookie.set_expires(expires_in);
self.cookies.private().add(user_cookie);
}
if let Some(mut adm_cookie) = self
.cookies
.private()
.get(crate::auth::AUTH_ADMIN_ID_SESSION)
{
let expires_in = time::OffsetDateTime::now_utc()
.checked_sub(time::Duration::days(100));
adm_cookie.set_path("/");
adm_cookie.set_expires(expires_in);
self.cookies.private().add(adm_cookie);
}
}
}
impl<T> ops::Deref for HttpContext<T> {
type Target = Arc<T>;
fn deref(&self) -> &Self::Target {
&self.context
}
}