apt: query the Launchpad PPA API through the shared HTTP client

This commit is contained in:
2026-09-18 13:09:46 +02:00
parent 941f91decf
commit c106ebe315
2 changed files with 31 additions and 22 deletions
+28 -20
View File
@@ -198,7 +198,12 @@ fn validate_keyring_dir(dir_uid: u32, mode: u32, euid: u32) -> Result<(), String
Ok(()) Ok(())
} }
/// Download and import a PPA key using Launchpad API /// Download and import a PPA key using the Launchpad API
///
/// The signing key fingerprint is looked up through the shared HTTP client;
/// the key itself is fetched from the keyserver with curl through the
/// context, because the key file must land in the context's filesystem
/// (which may be remote).
/// ///
/// # Arguments /// # Arguments
/// * `ctx` - Optional context to use /// * `ctx` - Optional context to use
@@ -229,33 +234,36 @@ pub async fn download_trust_ppa_key(
ppa_name ppa_name
); );
// Get PPA information from Launchpad API to get signing key fingerprint // Get PPA information from the Launchpad API to get the signing key
// Use the correct devel API endpoint // fingerprint. The query is context-independent metadata, so it goes
let api_url = format!( // through the shared HTTP client (timeouts, retries) rather than
"https://api.launchpad.net/1.0/~{}/+archive/ubuntu/{}", // shelling out to curl.
ppa_owner, ppa_name let api_url = crate::launchpad::archive_url(ppa_owner, ppa_name);
);
log::debug!("Querying Launchpad API: {}", api_url); log::debug!("Querying Launchpad API: {}", api_url);
let api_response = ctx let response = distro_info::http_get_retried(&api_url).await.map_err(|e| {
.command("curl") format!(
.arg("-s") "Failed to query Launchpad API for PPA {}/{}: {}",
.arg("-f") ppa_owner, ppa_name, e
.arg("-H") )
.arg("Accept: application/json") })?;
.arg(&api_url) if !response.status().is_success() {
.output()?;
if !api_response.status.success() {
return Err(format!( return Err(format!(
"Failed to query Launchpad API for PPA {}/{}", "Failed to query Launchpad API for PPA {}/{}: HTTP {}",
ppa_owner, ppa_name ppa_owner,
ppa_name,
response.status()
) )
.into()); .into());
} }
// Parse the JSON response to extract the signing key fingerprint // Parse the JSON response to extract the signing key fingerprint
let api_response_str = String::from_utf8_lossy(&api_response.stdout); let api_response_str = response.text().await.map_err(|e| {
format!(
"Failed to read the Launchpad API response for PPA {}/{}: {}",
ppa_owner, ppa_name, e
)
})?;
let ppa_response: LaunchpadPpaResponse = let ppa_response: LaunchpadPpaResponse =
serde_json::from_str(&api_response_str).map_err(|e| { serde_json::from_str(&api_response_str).map_err(|e| {
format!( format!(
+3 -2
View File
@@ -92,8 +92,9 @@ fn person_url(user: &str) -> String {
} }
/// URL of the Launchpad API resource of a PPA (`~user/+archive/ubuntu/name` /// URL of the Launchpad API resource of a PPA (`~user/+archive/ubuntu/name`
/// covers the default `ppa` archive and named archives alike) /// covers the default `ppa` archive and named archives alike); shared by the
fn archive_url(user: &str, ppa: &str) -> String { /// put-side pre-flight checks and the apt keyring's fingerprint lookup
pub(crate) fn archive_url(user: &str, ppa: &str) -> String {
format!("{API_BASE}/~{user}/+archive/ubuntu/{ppa}") format!("{API_BASE}/~{user}/+archive/ubuntu/{ppa}")
} }