lib-humus 0.6.0

Helps creating configurable frontends for humans and computers using axum, Tera and toml.
Documentation
// SPDX-FileCopyrightText: 2026 Slatian <baschdel@disroot.org>
//
// SPDX-License-Identifier: AGPL-3.0-or-later

//! Helpers for turning a request into a [HumusFormatIdentifier].
//!
//! They are supposed to be used inside a [tower::Service]. For a ready to use implementation see [TemplateSettingsLayer][crate::middleware::TemplateSettingsLayer] and [TemplateSettingsService][crate::middleware::TemplateSettingsService].

use axum::extract::Query;
use axum::{body::Body, http::Request};

use crate::headers::AcceptHeader;
use crate::templating::FormatChooser;
use crate::templating::HumusFormatIdentifier;

#[derive(serde::Deserialize)]
struct FormatQuery {
	format: Option<HumusFormatIdentifier>,
}

/// Extracts the format from the `format` URL-query parameter.
pub fn extract_format_from_request_uri(req: &Request<Body>) -> Option<HumusFormatIdentifier> {
	match Query::<FormatQuery>::try_from_uri(req.uri()) {
		Ok(Query(format_query)) => {
			// HumusFormatIdentifier is validated in the templating engine based on what is available for the given view.
			format_query.format
		}
		Err(_e) => {
			None // Ignore error for now.
		}
	}
}

/// Extracts the format from the HTTP `Accept` Header.
pub fn extract_format_from_request_accept_header(
	req: &Request<Body>,
	media_type_based_format_chooser: &FormatChooser,
) -> Option<HumusFormatIdentifier> {
	let accept_header = req.headers().get("accept")?.to_str().ok()?;
	let accept_header = AcceptHeader::new(accept_header);
	media_type_based_format_chooser.choose_from_accept_header(&accept_header)
}

/// Extracts the format from the HTTP `User-Agent` Header.
pub fn extract_format_from_request_user_agent_header(
	req: &Request<Body>,
	media_type_based_format_chooser: &FormatChooser,
) -> Option<HumusFormatIdentifier> {
	let user_agent_header = req.headers().get("user-agent")?.to_str().ok()?;
	media_type_based_format_chooser.choose_from_user_agent(user_agent_header)
}