Skip to main content

pray_core/
fetch.rs

1//! Bounded HTTP and torrent helpers shared by registry install and transport adapters.
2
3use crate::paths::remove_path_if_exists;
4use crate::registry_torrent::{fetch_torrent_artifact_to_path, fetch_torrent_manifest};
5use crate::PrayResult;
6use std::fs;
7use std::time::{SystemTime, UNIX_EPOCH};
8
9pub use crate::registry_http::{
10    http_get, http_get_with_headers, http_post, http_put, join_url, HttpResponse,
11};
12pub use crate::resource_limits::{MAX_HTTP_RESPONSE_BYTES, MAX_TORRENT_ARTIFACT_BYTES};
13
14/// Download a registry artifact using torrent pieces when a sidecar exists, else bounded HTTP GET.
15pub fn download_registry_artifact(
16    source_url: &str,
17    artifact_relative_path: &str,
18) -> PrayResult<Vec<u8>> {
19    let artifact_url = join_url(source_url, artifact_relative_path);
20    if let Some(manifest) = fetch_torrent_manifest(source_url, artifact_relative_path)? {
21        let stamp = SystemTime::now()
22            .duration_since(UNIX_EPOCH)
23            .map(|duration| duration.as_nanos())
24            .unwrap_or(0);
25        let staging = std::env::temp_dir().join(format!("pray-torrent-{stamp}"));
26        fs::create_dir_all(&staging)?;
27        let destination = staging.join("package.praypkg");
28        let result = fetch_torrent_artifact_to_path(
29            source_url,
30            artifact_relative_path,
31            &manifest,
32            &destination,
33        );
34        let bytes = match result {
35            Ok(bytes) => bytes,
36            Err(error) => {
37                let _ = remove_path_if_exists(&staging);
38                return Err(error);
39            }
40        };
41        let _ = remove_path_if_exists(&staging);
42        return Ok(bytes);
43    }
44    http_get(&artifact_url)
45}