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(())
}
/// 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
/// * `ctx` - Optional context to use
@@ -229,33 +234,36 @@ pub async fn download_trust_ppa_key(
ppa_name
);
// Get PPA information from Launchpad API to get signing key fingerprint
// Use the correct devel API endpoint
let api_url = format!(
"https://api.launchpad.net/1.0/~{}/+archive/ubuntu/{}",
ppa_owner, ppa_name
);
// Get PPA information from the Launchpad API to get the signing key
// fingerprint. The query is context-independent metadata, so it goes
// through the shared HTTP client (timeouts, retries) rather than
// shelling out to curl.
let api_url = crate::launchpad::archive_url(ppa_owner, ppa_name);
log::debug!("Querying Launchpad API: {}", api_url);
let api_response = ctx
.command("curl")
.arg("-s")
.arg("-f")
.arg("-H")
.arg("Accept: application/json")
.arg(&api_url)
.output()?;
if !api_response.status.success() {
let response = distro_info::http_get_retried(&api_url).await.map_err(|e| {
format!(
"Failed to query Launchpad API for PPA {}/{}: {}",
ppa_owner, ppa_name, e
)
})?;
if !response.status().is_success() {
return Err(format!(
"Failed to query Launchpad API for PPA {}/{}",
ppa_owner, ppa_name
"Failed to query Launchpad API for PPA {}/{}: HTTP {}",
ppa_owner,
ppa_name,
response.status()
)
.into());
}
// 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 =
serde_json::from_str(&api_response_str).map_err(|e| {
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`
/// covers the default `ppa` archive and named archives alike)
fn archive_url(user: &str, ppa: &str) -> String {
/// covers the default `ppa` archive and named archives alike); shared by the
/// 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}")
}