use axum::http::HeaderMap;
use crate::auth::request_credentials::RequestCredentials;
#[derive(Debug, PartialEq)]
pub enum ExtractError {
Missing,
UnsupportedLocation(String),
}
pub fn extract_request_credentials(
headers: &HeaderMap,
header_location: &str,
header_name: &str,
) -> Result<RequestCredentials, ExtractError> {
if header_location != "header" {
return Err(ExtractError::UnsupportedLocation(
header_location.to_string(),
));
}
let value = headers
.get(header_name)
.and_then(|value| value.to_str().ok())
.filter(|value| !value.is_empty())
.ok_or(ExtractError::Missing)?;
Ok(RequestCredentials {
header_name: header_name.to_string(),
value: value.to_string(),
})
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn extracts_a_present_header() {
let mut headers = HeaderMap::new();
headers.insert("Authorization", "Bearer abc".parse().unwrap());
let creds = extract_request_credentials(&headers, "header", "Authorization").unwrap();
assert_eq!(creds.header_name, "Authorization");
assert_eq!(creds.value, "Bearer abc");
}
#[test]
fn errors_when_the_header_is_absent() {
let headers = HeaderMap::new();
assert_eq!(
extract_request_credentials(&headers, "header", "Authorization"),
Err(ExtractError::Missing)
);
}
#[test]
fn errors_when_the_header_is_present_but_empty() {
let mut headers = HeaderMap::new();
headers.insert("X-Api-Key", "".parse().unwrap());
assert_eq!(
extract_request_credentials(&headers, "header", "X-Api-Key"),
Err(ExtractError::Missing)
);
}
#[test]
fn rejects_query_and_cookie_locations() {
let headers = HeaderMap::new();
assert_eq!(
extract_request_credentials(&headers, "query", "api_key"),
Err(ExtractError::UnsupportedLocation("query".to_string()))
);
assert_eq!(
extract_request_credentials(&headers, "cookie", "session"),
Err(ExtractError::UnsupportedLocation("cookie".to_string()))
);
assert_eq!(
extract_request_credentials(&headers, "none", ""),
Err(ExtractError::UnsupportedLocation("none".to_string()))
);
}
}