From a7893ddbdad4a51183b4a0d6cd1a5b623277c1a7 Mon Sep 17 00:00:00 2001 From: Lennart <18233294+lennart-k@users.noreply.github.com> Date: Tue, 30 Dec 2025 13:53:42 +0100 Subject: [PATCH] Replace deprecated axum Host extractor with Host header --- crates/frontend/src/nextcloud_login/routes.rs | 8 ++++---- crates/frontend/src/routes/app_token.rs | 14 +++++++------- crates/frontend/src/routes/login.rs | 8 ++++---- crates/frontend/src/routes/user.rs | 14 ++++++++------ crates/oidc/src/lib.rs | 9 ++++++--- 5 files changed, 29 insertions(+), 24 deletions(-) diff --git a/crates/frontend/src/nextcloud_login/routes.rs b/crates/frontend/src/nextcloud_login/routes.rs index b0056ad..fab86b1 100644 --- a/crates/frontend/src/nextcloud_login/routes.rs +++ b/crates/frontend/src/nextcloud_login/routes.rs @@ -9,9 +9,9 @@ use axum::{ extract::Path, response::{Html, IntoResponse, Response}, }; -use axum_extra::{TypedHeader, extract::Host}; +use axum_extra::TypedHeader; use chrono::{Duration, Utc}; -use headers::UserAgent; +use headers::{Host, UserAgent}; use http::StatusCode; use rustical_store::auth::{AuthenticationProvider, Principal}; use serde::{Deserialize, Serialize}; @@ -21,7 +21,7 @@ use tracing::instrument; pub async fn post_nextcloud_login( Extension(state): Extension>, TypedHeader(user_agent): TypedHeader, - Host(host): Host, + TypedHeader(host): TypedHeader, ) -> Json { let flow_id = uuid::Uuid::new_v4().to_string(); let token = uuid::Uuid::new_v4().to_string(); @@ -150,7 +150,7 @@ pub async fn post_nextcloud_flow( user: Principal, Extension(state): Extension>, Path(flow_id): Path, - Host(host): Host, + TypedHeader(host): TypedHeader, Form(form): Form, ) -> Result { if let Some(flow) = state.flows.write().await.get_mut(&flow_id) { diff --git a/crates/frontend/src/routes/app_token.rs b/crates/frontend/src/routes/app_token.rs index 6fc6e26..8e6f30c 100644 --- a/crates/frontend/src/routes/app_token.rs +++ b/crates/frontend/src/routes/app_token.rs @@ -7,8 +7,8 @@ use axum::{ extract::Path, response::{IntoResponse, Redirect, Response}, }; -use axum_extra::extract::Host; -use headers::{ContentType, HeaderMapExt}; +use axum_extra::TypedHeader; +use headers::{ContentType, HeaderMapExt, Host}; use http::{HeaderValue, StatusCode, header}; use percent_encoding::{CONTROLS, utf8_percent_encode}; use rand::{Rng, distr::Alphanumeric}; @@ -50,7 +50,7 @@ pub async fn route_post_app_token( user: Principal, Extension(auth_provider): Extension>, Path(user_id): Path, - Host(hostname): Host, + TypedHeader(host): TypedHeader, Form(PostAppTokenForm { apple, name }): Form, ) -> Result { assert!(!name.is_empty()); @@ -66,10 +66,10 @@ pub async fn route_post_app_token( if apple { let profile = AppleConfig { token_name: name, - account_description: format!("{}@{}", &user.id, &hostname), - hostname: hostname.clone(), - caldav_principal_url: format!("https://{hostname}/caldav-compat/principal/{user_id}"), - carddav_principal_url: format!("https://{hostname}/carddav/principal/{user_id}"), + account_description: format!("{}@{}", &user.id, &host), + hostname: host.to_string(), + caldav_principal_url: format!("https://{host}/caldav-compat/principal/{user_id}"), + carddav_principal_url: format!("https://{host}/carddav/principal/{user_id}"), user: user.id.clone(), token, caldav_profile_uuid: Uuid::new_v4(), diff --git a/crates/frontend/src/routes/login.rs b/crates/frontend/src/routes/login.rs index 39682c5..f371e32 100644 --- a/crates/frontend/src/routes/login.rs +++ b/crates/frontend/src/routes/login.rs @@ -1,5 +1,3 @@ -use std::sync::Arc; - use crate::{FrontendConfig, OidcConfig, pages::DefaultLayoutData}; use askama::Template; use askama_web::WebTemplate; @@ -8,10 +6,12 @@ use axum::{ extract::Query, response::{IntoResponse, Redirect, Response}, }; -use axum_extra::extract::Host; +use axum_extra::TypedHeader; +use headers::Host; use http::StatusCode; use rustical_store::auth::AuthenticationProvider; use serde::Deserialize; +use std::sync::Arc; use tower_sessions::Session; use tracing::{instrument, warn}; use url::Url; @@ -73,7 +73,7 @@ pub async fn route_post_login( Extension(auth_provider): Extension>, Extension(config): Extension, session: Session, - Host(host): Host, + TypedHeader(host): TypedHeader, Form(PostLoginForm { username, password, diff --git a/crates/frontend/src/routes/user.rs b/crates/frontend/src/routes/user.rs index 237b824..38a9e22 100644 --- a/crates/frontend/src/routes/user.rs +++ b/crates/frontend/src/routes/user.rs @@ -1,5 +1,6 @@ use std::sync::Arc; +use crate::pages::user::{Section, UserPage}; use askama::Template; use askama_web::WebTemplate; use axum::{ @@ -7,13 +8,11 @@ use axum::{ extract::Path, response::{IntoResponse, Redirect}, }; -use axum_extra::{TypedHeader, extract::Host}; -use headers::UserAgent; +use axum_extra::TypedHeader; +use headers::{Host, UserAgent}; use http::StatusCode; use rustical_store::auth::{AppToken, AuthenticationProvider, Principal}; -use crate::pages::user::{Section, UserPage}; - impl Section for ProfileSection { fn name() -> &'static str { "profile" @@ -33,7 +32,7 @@ pub async fn route_user_named( Path(user_id): Path, Extension(auth_provider): Extension>, TypedHeader(user_agent): TypedHeader, - Host(host): Host, + TypedHeader(host): TypedHeader, user: Principal, ) -> impl IntoResponse { if user_id != user.id { @@ -41,7 +40,10 @@ pub async fn route_user_named( } let is_apple = user_agent.as_str().contains("Apple") || user_agent.as_str().contains("Mac OS"); - let davx5_hostname = user_agent.as_str().contains("Android").then_some(host); + let davx5_hostname = user_agent + .as_str() + .contains("Android") + .then_some(host.to_string()); UserPage { section: ProfileSection { diff --git a/crates/oidc/src/lib.rs b/crates/oidc/src/lib.rs index 5e74250..6207679 100644 --- a/crates/oidc/src/lib.rs +++ b/crates/oidc/src/lib.rs @@ -5,10 +5,11 @@ use axum::{ extract::Query, response::{IntoResponse, Redirect, Response}, }; -use axum_extra::extract::Host; +use axum_extra::TypedHeader; pub use config::OidcConfig; use config::UserIdClaim; use error::OidcError; +use headers::Host; use openidconnect::{ AuthenticationFlow, AuthorizationCode, CsrfToken, EndpointMaybeSet, EndpointNotSet, EndpointSet, IssuerUrl, Nonce, OAuth2TokenResponse, PkceCodeChallenge, PkceCodeVerifier, @@ -100,10 +101,12 @@ pub struct GetOidcForm { pub async fn route_post_oidc( Extension(oidc_config): Extension, session: Session, - Host(host): Host, + TypedHeader(host): TypedHeader, Form(GetOidcForm { redirect_uri }): Form, ) -> Result { + dbg!(&host); let callback_uri = format!("https://{host}/frontend/login/oidc/callback"); + dbg!(&callback_uri); let http_client = get_http_client(); let oidc_client = get_oidc_client( @@ -155,7 +158,7 @@ pub async fn route_get_oidc_callback( Extension(service_config): Extension, session: Session, Query(AuthCallbackQuery { code, iss, state }): Query, - Host(host): Host, + TypedHeader(host): TypedHeader, ) -> Result { let callback_uri = format!("https://{host}/frontend/login/oidc/callback");