use salvo_core::http::cookie::time::Duration;
use salvo_core::http::cookie::{Cookie, SameSite};
use salvo_core::{Depot, Request, Response};
use super::{Flash, FlashHandler, FlashStore};
#[derive(Debug)]
#[non_exhaustive]
pub struct CookieStore {
pub max_age: Duration,
pub same_site: SameSite,
pub http_only: bool,
pub path: String,
pub name: String,
}
impl Default for CookieStore {
fn default() -> Self {
Self::new()
}
}
impl CookieStore {
pub fn new() -> Self {
Self {
max_age: Duration::seconds(60),
same_site: SameSite::Lax,
http_only: true,
path: "/".into(),
name: "salvo.flash".into(),
}
}
pub fn name(mut self, name: impl Into<String>) -> Self {
self.name = name.into();
self
}
pub fn max_age(mut self, max_age: Duration) -> Self {
self.max_age = max_age;
self
}
pub fn same_site(mut self, same_site: SameSite) -> Self {
self.same_site = same_site;
self
}
pub fn http_only(mut self, http_only: bool) -> Self {
self.http_only = http_only;
self
}
pub fn path(mut self, path: impl Into<String>) -> Self {
self.path = path.into();
self
}
pub fn into_handler(self) -> FlashHandler<CookieStore> {
FlashHandler::new(self)
}
}
impl FlashStore for CookieStore {
async fn load_flash(&self, req: &mut Request, _depot: &mut Depot) -> Option<Flash> {
match req.cookie(&self.name) {
None => None,
Some(cookie) => match serde_json::from_str(cookie.value()) {
Ok(flash) => Some(flash),
Err(e) => {
tracing::error!(error = ?e, "deserialize flash cookie failed");
None
}
},
}
}
async fn save_flash(&self, _req: &mut Request, _depot: &mut Depot, res: &mut Response, flash: Flash) {
res.add_cookie(
Cookie::build((self.name.clone(), serde_json::to_string(&flash).unwrap_or_default()))
.max_age(self.max_age)
.path(self.path.clone())
.same_site(self.same_site)
.http_only(self.http_only)
.build(),
);
}
async fn clear_flash(&self, _depot: &mut Depot, res: &mut Response) {
res.add_cookie(
Cookie::build((self.name.clone(), ""))
.max_age(Duration::seconds(0))
.same_site(self.same_site)
.http_only(self.http_only)
.path(self.path.clone())
.build(),
);
}
}