use sa_token_adapter::context::{CookieOptions, SaRequest, SaResponse, SameSite};
use sa_token_adapter::utils::extract_bearer_or_value;
use crate::config::{SaTokenConfig, TokenCookieConfig};
use crate::token::TokenValue;
pub fn read_token<R: SaRequest>(req: &R, config: &SaTokenConfig) -> Option<String> {
let name = config.token_name.as_str();
let mut raw: Option<String> = None;
if config.is_read_header {
if let Some(v) = req.get_header(name) {
if !v.trim().is_empty() {
raw = Some(v);
}
}
if raw.is_none() && !name.eq_ignore_ascii_case("authorization") {
if let Some(v) = req.get_header("Authorization") {
if !v.trim().is_empty() {
raw = Some(v);
}
}
}
}
if raw.is_none() && config.is_read_cookie {
if let Some(v) = req.get_cookie(name) {
if !v.trim().is_empty() {
raw = Some(v);
}
}
}
if raw.is_none() && config.is_read_body {
if let Some(v) = req.get_param(name) {
if !v.trim().is_empty() {
raw = Some(v);
}
}
}
let raw = raw?;
apply_token_prefix(raw.trim(), config.token_prefix.as_deref())
}
pub fn apply_token_prefix(raw: &str, prefix: Option<&str>) -> Option<String> {
if raw.is_empty() {
return None;
}
match prefix {
None => {
let s = extract_bearer_or_value(raw);
if s.is_empty() { None } else { Some(s) }
}
Some(p) => {
if let Some(rest) = raw.strip_prefix(p) {
let rest = rest.trim();
if rest.is_empty() {
None
} else {
Some(rest.to_string())
}
} else {
None
}
}
}
}
pub fn read_token_from_maps(
headers: &std::collections::HashMap<String, String>,
query: &std::collections::HashMap<String, String>,
config: &SaTokenConfig,
) -> Option<String> {
let name = config.token_name.as_str();
let mut raw: Option<String> = None;
if config.is_read_header {
if let Some(v) = headers.get(name).filter(|s| !s.trim().is_empty()) {
raw = Some(v.clone());
}
if raw.is_none() && !name.eq_ignore_ascii_case("authorization") {
if let Some(v) = headers
.get("Authorization")
.or_else(|| headers.get("authorization"))
.filter(|s| !s.trim().is_empty())
{
raw = Some(v.clone());
}
}
if raw.is_none() {
if let Some(v) = headers
.get("Sec-WebSocket-Protocol")
.filter(|s| !s.trim().is_empty())
{
raw = Some(v.clone());
}
}
}
if raw.is_none() && config.is_read_body {
if let Some(v) = query.get(name).filter(|s| !s.trim().is_empty()) {
raw = Some(v.clone());
}
if raw.is_none() {
if let Some(v) = query.get("token").filter(|s| !s.trim().is_empty()) {
raw = Some(v.clone());
}
}
}
apply_token_prefix(raw?.trim(), config.token_prefix.as_deref())
}
pub fn write_token_cookie<R: SaResponse>(res: &mut R, token: &TokenValue, config: &SaTokenConfig) {
if !config.cookie.is_write_cookie {
return;
}
let opts = cookie_options(&config.cookie, config.timeout);
res.set_cookie(config.token_name.as_str(), token.as_str(), opts);
}
pub fn delete_token_cookie<R: SaResponse>(res: &mut R, config: &SaTokenConfig) {
if !config.cookie.is_write_cookie {
return;
}
let mut opts = cookie_options(&config.cookie, 0);
opts.max_age = Some(0);
res.set_cookie(config.token_name.as_str(), "", opts);
}
fn cookie_options(cookie: &TokenCookieConfig, max_age_secs: i64) -> CookieOptions {
CookieOptions {
domain: cookie.domain.clone(),
path: cookie.path.clone().or_else(|| Some("/".into())),
max_age: if max_age_secs < 0 {
None
} else {
Some(max_age_secs)
},
http_only: cookie.http_only,
secure: cookie.secure,
same_site: cookie.same_site.or(Some(SameSite::Lax)),
}
}