Replace deprecated axum Host extractor with Host header

This commit is contained in:
Lennart
2025-12-30 13:53:42 +01:00
parent ed7becffc2
commit a7893ddbda
5 changed files with 29 additions and 24 deletions

View File

@@ -9,9 +9,9 @@ use axum::{
extract::Path, extract::Path,
response::{Html, IntoResponse, Response}, response::{Html, IntoResponse, Response},
}; };
use axum_extra::{TypedHeader, extract::Host}; use axum_extra::TypedHeader;
use chrono::{Duration, Utc}; use chrono::{Duration, Utc};
use headers::UserAgent; use headers::{Host, UserAgent};
use http::StatusCode; use http::StatusCode;
use rustical_store::auth::{AuthenticationProvider, Principal}; use rustical_store::auth::{AuthenticationProvider, Principal};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@@ -21,7 +21,7 @@ use tracing::instrument;
pub async fn post_nextcloud_login( pub async fn post_nextcloud_login(
Extension(state): Extension<Arc<NextcloudFlows>>, Extension(state): Extension<Arc<NextcloudFlows>>,
TypedHeader(user_agent): TypedHeader<UserAgent>, TypedHeader(user_agent): TypedHeader<UserAgent>,
Host(host): Host, TypedHeader(host): TypedHeader<Host>,
) -> Json<NextcloudLoginResponse> { ) -> Json<NextcloudLoginResponse> {
let flow_id = uuid::Uuid::new_v4().to_string(); let flow_id = uuid::Uuid::new_v4().to_string();
let token = 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, user: Principal,
Extension(state): Extension<Arc<NextcloudFlows>>, Extension(state): Extension<Arc<NextcloudFlows>>,
Path(flow_id): Path<String>, Path(flow_id): Path<String>,
Host(host): Host, TypedHeader(host): TypedHeader<Host>,
Form(form): Form<NextcloudAuthorizeForm>, Form(form): Form<NextcloudAuthorizeForm>,
) -> Result<Response, rustical_store::Error> { ) -> Result<Response, rustical_store::Error> {
if let Some(flow) = state.flows.write().await.get_mut(&flow_id) { if let Some(flow) = state.flows.write().await.get_mut(&flow_id) {

View File

@@ -7,8 +7,8 @@ use axum::{
extract::Path, extract::Path,
response::{IntoResponse, Redirect, Response}, response::{IntoResponse, Redirect, Response},
}; };
use axum_extra::extract::Host; use axum_extra::TypedHeader;
use headers::{ContentType, HeaderMapExt}; use headers::{ContentType, HeaderMapExt, Host};
use http::{HeaderValue, StatusCode, header}; use http::{HeaderValue, StatusCode, header};
use percent_encoding::{CONTROLS, utf8_percent_encode}; use percent_encoding::{CONTROLS, utf8_percent_encode};
use rand::{Rng, distr::Alphanumeric}; use rand::{Rng, distr::Alphanumeric};
@@ -50,7 +50,7 @@ pub async fn route_post_app_token<AP: AuthenticationProvider>(
user: Principal, user: Principal,
Extension(auth_provider): Extension<Arc<AP>>, Extension(auth_provider): Extension<Arc<AP>>,
Path(user_id): Path<String>, Path(user_id): Path<String>,
Host(hostname): Host, TypedHeader(host): TypedHeader<Host>,
Form(PostAppTokenForm { apple, name }): Form<PostAppTokenForm>, Form(PostAppTokenForm { apple, name }): Form<PostAppTokenForm>,
) -> Result<Response, rustical_store::Error> { ) -> Result<Response, rustical_store::Error> {
assert!(!name.is_empty()); assert!(!name.is_empty());
@@ -66,10 +66,10 @@ pub async fn route_post_app_token<AP: AuthenticationProvider>(
if apple { if apple {
let profile = AppleConfig { let profile = AppleConfig {
token_name: name, token_name: name,
account_description: format!("{}@{}", &user.id, &hostname), account_description: format!("{}@{}", &user.id, &host),
hostname: hostname.clone(), hostname: host.to_string(),
caldav_principal_url: format!("https://{hostname}/caldav-compat/principal/{user_id}"), caldav_principal_url: format!("https://{host}/caldav-compat/principal/{user_id}"),
carddav_principal_url: format!("https://{hostname}/carddav/principal/{user_id}"), carddav_principal_url: format!("https://{host}/carddav/principal/{user_id}"),
user: user.id.clone(), user: user.id.clone(),
token, token,
caldav_profile_uuid: Uuid::new_v4(), caldav_profile_uuid: Uuid::new_v4(),

View File

@@ -1,5 +1,3 @@
use std::sync::Arc;
use crate::{FrontendConfig, OidcConfig, pages::DefaultLayoutData}; use crate::{FrontendConfig, OidcConfig, pages::DefaultLayoutData};
use askama::Template; use askama::Template;
use askama_web::WebTemplate; use askama_web::WebTemplate;
@@ -8,10 +6,12 @@ use axum::{
extract::Query, extract::Query,
response::{IntoResponse, Redirect, Response}, response::{IntoResponse, Redirect, Response},
}; };
use axum_extra::extract::Host; use axum_extra::TypedHeader;
use headers::Host;
use http::StatusCode; use http::StatusCode;
use rustical_store::auth::AuthenticationProvider; use rustical_store::auth::AuthenticationProvider;
use serde::Deserialize; use serde::Deserialize;
use std::sync::Arc;
use tower_sessions::Session; use tower_sessions::Session;
use tracing::{instrument, warn}; use tracing::{instrument, warn};
use url::Url; use url::Url;
@@ -73,7 +73,7 @@ pub async fn route_post_login<AP: AuthenticationProvider>(
Extension(auth_provider): Extension<Arc<AP>>, Extension(auth_provider): Extension<Arc<AP>>,
Extension(config): Extension<FrontendConfig>, Extension(config): Extension<FrontendConfig>,
session: Session, session: Session,
Host(host): Host, TypedHeader(host): TypedHeader<Host>,
Form(PostLoginForm { Form(PostLoginForm {
username, username,
password, password,

View File

@@ -1,5 +1,6 @@
use std::sync::Arc; use std::sync::Arc;
use crate::pages::user::{Section, UserPage};
use askama::Template; use askama::Template;
use askama_web::WebTemplate; use askama_web::WebTemplate;
use axum::{ use axum::{
@@ -7,13 +8,11 @@ use axum::{
extract::Path, extract::Path,
response::{IntoResponse, Redirect}, response::{IntoResponse, Redirect},
}; };
use axum_extra::{TypedHeader, extract::Host}; use axum_extra::TypedHeader;
use headers::UserAgent; use headers::{Host, UserAgent};
use http::StatusCode; use http::StatusCode;
use rustical_store::auth::{AppToken, AuthenticationProvider, Principal}; use rustical_store::auth::{AppToken, AuthenticationProvider, Principal};
use crate::pages::user::{Section, UserPage};
impl Section for ProfileSection { impl Section for ProfileSection {
fn name() -> &'static str { fn name() -> &'static str {
"profile" "profile"
@@ -33,7 +32,7 @@ pub async fn route_user_named<AP: AuthenticationProvider>(
Path(user_id): Path<String>, Path(user_id): Path<String>,
Extension(auth_provider): Extension<Arc<AP>>, Extension(auth_provider): Extension<Arc<AP>>,
TypedHeader(user_agent): TypedHeader<UserAgent>, TypedHeader(user_agent): TypedHeader<UserAgent>,
Host(host): Host, TypedHeader(host): TypedHeader<Host>,
user: Principal, user: Principal,
) -> impl IntoResponse { ) -> impl IntoResponse {
if user_id != user.id { if user_id != user.id {
@@ -41,7 +40,10 @@ pub async fn route_user_named<AP: AuthenticationProvider>(
} }
let is_apple = user_agent.as_str().contains("Apple") || user_agent.as_str().contains("Mac OS"); 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 { UserPage {
section: ProfileSection { section: ProfileSection {

View File

@@ -5,10 +5,11 @@ use axum::{
extract::Query, extract::Query,
response::{IntoResponse, Redirect, Response}, response::{IntoResponse, Redirect, Response},
}; };
use axum_extra::extract::Host; use axum_extra::TypedHeader;
pub use config::OidcConfig; pub use config::OidcConfig;
use config::UserIdClaim; use config::UserIdClaim;
use error::OidcError; use error::OidcError;
use headers::Host;
use openidconnect::{ use openidconnect::{
AuthenticationFlow, AuthorizationCode, CsrfToken, EndpointMaybeSet, EndpointNotSet, AuthenticationFlow, AuthorizationCode, CsrfToken, EndpointMaybeSet, EndpointNotSet,
EndpointSet, IssuerUrl, Nonce, OAuth2TokenResponse, PkceCodeChallenge, PkceCodeVerifier, EndpointSet, IssuerUrl, Nonce, OAuth2TokenResponse, PkceCodeChallenge, PkceCodeVerifier,
@@ -100,10 +101,12 @@ pub struct GetOidcForm {
pub async fn route_post_oidc( pub async fn route_post_oidc(
Extension(oidc_config): Extension<OidcConfig>, Extension(oidc_config): Extension<OidcConfig>,
session: Session, session: Session,
Host(host): Host, TypedHeader(host): TypedHeader<Host>,
Form(GetOidcForm { redirect_uri }): Form<GetOidcForm>, Form(GetOidcForm { redirect_uri }): Form<GetOidcForm>,
) -> Result<Response, OidcError> { ) -> Result<Response, OidcError> {
dbg!(&host);
let callback_uri = format!("https://{host}/frontend/login/oidc/callback"); let callback_uri = format!("https://{host}/frontend/login/oidc/callback");
dbg!(&callback_uri);
let http_client = get_http_client(); let http_client = get_http_client();
let oidc_client = get_oidc_client( let oidc_client = get_oidc_client(
@@ -155,7 +158,7 @@ pub async fn route_get_oidc_callback<US: UserStore + Clone>(
Extension(service_config): Extension<OidcServiceConfig>, Extension(service_config): Extension<OidcServiceConfig>,
session: Session, session: Session,
Query(AuthCallbackQuery { code, iss, state }): Query<AuthCallbackQuery>, Query(AuthCallbackQuery { code, iss, state }): Query<AuthCallbackQuery>,
Host(host): Host, TypedHeader(host): TypedHeader<Host>,
) -> Result<Response, OidcError> { ) -> Result<Response, OidcError> {
let callback_uri = format!("https://{host}/frontend/login/oidc/callback"); let callback_uri = format!("https://{host}/frontend/login/oidc/callback");