qol(http): replaced all explicit header setting with axum cookie jar

This commit is contained in:
2026-07-15 14:41:54 +01:00
parent ce064ba9c8
commit 7262a06f28
3 changed files with 46 additions and 38 deletions
Generated
+34
View File
@@ -366,6 +366,28 @@ dependencies = [
"tracing",
]
[[package]]
name = "axum-extra"
version = "0.12.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be44683b41ccb9ab2d23a5230015c9c3c55be97a25e4428366de8873103f7970"
dependencies = [
"axum",
"axum-core",
"bytes",
"cookie",
"futures-core",
"futures-util",
"http",
"http-body",
"http-body-util",
"mime",
"pin-project-lite",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "base16ct"
version = "0.2.0"
@@ -682,6 +704,17 @@ version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
[[package]]
name = "cookie"
version = "0.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747"
dependencies = [
"percent-encoding",
"time",
"version_check",
]
[[package]]
name = "core-foundation-sys"
version = "0.8.7"
@@ -2871,6 +2904,7 @@ dependencies = [
"argon2",
"async-broadcast",
"axum",
"axum-extra",
"bytes",
"chrono",
"dashmap",
+1
View File
@@ -37,3 +37,4 @@ rubato = "3.0.0"
chrono = "0.4.45"
regex = "1"
thiserror = "2.0.18"
axum-extra = { version = "0.12.6", features = ["cookie"] }
+11 -38
View File
@@ -6,6 +6,7 @@ use std::{
},
};
use axum_extra::extract::{CookieJar, cookie::Cookie};
use regex::Regex;
// The Rust `regex` crate is guaranteed linear-time and therefore does NOT
@@ -206,22 +207,6 @@ struct CreateStreamKeyBody {
label: String,
}
fn extract_session_token(headers: &HeaderMap) -> Option<String> {
// Check bare `session` header first (curl / API clients)
if let Some(v) = headers.get("session") {
return Some(v.to_str().ok()?.to_string());
}
// Fall back to Cookie header (browsers)
let cookie_header = headers.get("cookie")?.to_str().ok()?;
cookie_header
.split(';')
.find_map(|pair| {
let pair = pair.trim();
pair.strip_prefix("session=")
})
.map(|v| v.to_string())
}
struct AuthUser(entity::users::Model);
impl FromRequestParts<Arc<HttpServer>> for AuthUser {
@@ -231,9 +216,10 @@ impl FromRequestParts<Arc<HttpServer>> for AuthUser {
parts: &mut Parts,
state: &Arc<HttpServer>,
) -> Result<Self, HttpError> {
let token = extract_session_token(&parts.headers).ok_or(HttpError::Unauthorized)?;
let jar = CookieJar::from_request_parts(parts, state).await.unwrap();
let session = jar.get("session").ok_or(HttpError::Unauthorized)?;
let user = users::Entity::find_by_auth_session(&state.db, token)
let user = users::Entity::find_by_auth_session(&state.db, session.to_string())
.await?
.ok_or(HttpError::Unauthorized)?;
@@ -306,6 +292,7 @@ struct LoginResponse {
async fn login_handler(
State(state): State<Arc<HttpServer>>,
Json(payload): Json<LoginForm>,
jar: CookieJar,
) -> Result<impl IntoResponse, HttpError> {
let user = users::Entity::find_by_username(&state.db, payload.username.clone())
.await?
@@ -323,16 +310,8 @@ async fn login_handler(
let auth = auth_session::Entity::create(&state.db, user.id).await?;
let token = auth.value;
let mut meow = Response::new("".to_string());
// TODO: Replace with axum cookie jar https://docs.rs/axum-extra/latest/axum_extra/extract/cookie/struct.CookieJar.html
meow.headers_mut().insert(
SET_COOKIE,
format!("session={token}; SameSite=Strict; Path=/; Max-Age=2592000")
.parse()
.unwrap(),
);
*meow.status_mut() = StatusCode::OK;
Ok(meow)
let jar = jar.add(Cookie::new("session", token));
Ok((StatusCode::OK, jar))
}
#[derive(Deserialize)]
@@ -345,7 +324,8 @@ struct CreateUserForm {
async fn create_user_handler(
State(state): State<Arc<HttpServer>>,
Json(payload): Json<CreateUserForm>,
) -> Result<(HeaderMap, StatusCode), HttpError> {
jar: CookieJar,
) -> Result<impl IntoResponse, HttpError> {
if state.config.signup_code.is_empty() || payload.ref_token != state.config.signup_code {
warn!(username = %payload.username, "signup rejected: invalid signup code");
return Err(HttpError::Unauthorized);
@@ -372,15 +352,8 @@ async fn create_user_handler(
let session = auth_session::Entity::create(&state.db, user.id).await?;
let token = session.value;
let mut headers = HeaderMap::new();
// TODO: Replace with axum cookie jar https://docs.rs/axum-extra/latest/axum_extra/extract/cookie/struct.CookieJar.html
headers.insert(
SET_COOKIE,
format!("session={token}; HttpOnly; SameSite=Strict; Path=/")
.parse()
.unwrap(),
);
Ok((headers, StatusCode::OK))
let jar = jar.add(Cookie::new("session", token));
Ok((jar, StatusCode::OK))
}
async fn stream_handler(