[PATCH installer v3 35/38] fetch-answer: http: prefer json over toml for answer format

Christoph Heiss
2026-04-03T16:57:21Z

.../src/fetch_plugins/http.rs | 43 +++++++++++++++----
1 file changed, 34 insertions(+), 9 deletions(-)

diff --git a/proxmox-fetch-answer/src/fetch_plugins/http.rs b/proxmox-fetch-answer/src/fetch_plugins/http.rs
index 9e5a87a..6508721 100644
--- a/proxmox-fetch-answer/src/fetch_plugins/http.rs
+++ b/proxmox-fetch-answer/src/fetch_plugins/http.rs
@@ -6,9 +6,14 @@ use std::{
};

use proxmox_auto_installer::{sysinfo, utils::HttpOptions};
-use proxmox_installer_common::http::{self, header::HeaderMap,
+use proxmox_installer_common::http::{
+ self,
+ header::{HeaderMap, HeaderValue},
+};
+use proxmox_installer_types::answer::{
+ AutoInstallerConfig,
+ fetch::{AnswerFetchData, AnswerFetchDataSchema},
};
-use proxmox_installer_types::answer::fetch::{AnswerFetchData, AnswerFetchDataSchema};

static ANSWER_URL_SUBDOMAIN: &str = "proxmox-auto-installer";
static ANSWER_CERT_FP_SUBDOMAIN: &str = "proxmox-auto-installer-cert-fingerprint";
@@ -40,6 +45,14 @@ impl FetchFromHTTP {
/// needs to be either trusted by the root certs or a SHA256 fingerprint needs to be provided.
/// The SHA256 SSL fingerprint can either be defined in the ISO, as DHCP option, or as DNS TXT
/// record. If provided, the fingerprint provided in the ISO has preference.
+ ///
+ /// # Parameters
+ ///
+ /// * `settings` - HTTP fetch options from the baked-in auto-installer configuration.
+ ///
+ /// # Returns
+ ///
+ /// The TOML-formatted answer retrieved from the given server.
pub fn get_answer(settings: &HttpOptions) -> Result<String> {
let mut fingerprint: Option<String> = match settings.cert_fingerprint.clone() {
Some(fp) => {
@@ -74,14 +87,26 @@ impl FetchFromHTTP {
})?;

info!("Sending POST request to '{answer_url}'.");
+ let mut headers = HeaderMap::new();

- Ok(http::post(
- &answer_url,
- fingerprint.as_deref(),
- HeaderMap::new(),
- payload,
- )?
- .0)
+ // Prefer JSON answers over TOML. The TOML path might be deprecated in the future.
+ headers.insert(
+ http::header::ACCEPT,
+ HeaderValue::from_str("application/json, application/toml;q=0.5")?,
+ );
+
+ let (body, content_type) =
+ http::post(&answer_url, fingerprint.as_deref(), headers, payload)?;
+
+ if let Some(ct) = content_type
+ && ct.starts_with("application/json")
+ {
+ // do a round-trip with serde into TOML, if we received JSON from the server
+ let answer: AutoInstallerConfig = serde_json::from_str(&body)?;
+ Ok(toml::to_string(&answer)?)
+ } else {
+ Ok(body)
+ }
}

/// Fetches search domain from resolv.conf file
--
2.53.0