Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't pass auth header when downloading a package #4838

Merged
merged 2 commits into from
Jun 12, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 75 additions & 44 deletions lib/cli/src/commands/package/download.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
use std::path::PathBuf;
use std::{env::current_dir, path::PathBuf};

use anyhow::{bail, Context};
use dialoguer::console::{style, Emoji};
use indicatif::{ProgressBar, ProgressStyle};
use tempfile::NamedTempFile;
use wasmer_config::package::{PackageIdent, PackageSource};
use wasmer_registry::wasmer_env::WasmerEnv;
use wasmer_wasix::http::reqwest::get_proxy;

use crate::opts::{ApiOpts, WasmerEnv};

/// Download a package from the registry.
#[derive(clap::Parser, Debug)]
pub struct PackageDownload {
#[clap(flatten)]
env: WasmerEnv,
pub api: ApiOpts,

#[clap(flatten)]
pub env: WasmerEnv,

/// Verify that the downloaded file is a valid package.
#[clap(long)]
Expand All @@ -21,7 +25,7 @@ pub struct PackageDownload {
/// Path where the package file should be written to.
/// If not specified, the data will be written to stdout.
#[clap(short = 'o', long)]
out_path: PathBuf,
out_path: Option<PathBuf>,

/// Run the download command without any output
#[clap(long)]
Expand Down Expand Up @@ -63,7 +67,7 @@ impl PackageDownload {

step_num += 1;

if let Some(parent) = self.out_path.parent() {
if let Some(parent) = self.out_path.as_ref().and_then(|p| p.parent()) {
match parent.metadata() {
Ok(m) => {
if !m.is_dir() {
Expand Down Expand Up @@ -91,53 +95,70 @@ impl PackageDownload {

step_num += 1;

let (download_url, token, ident) = match &self.package {
let (download_url, ident, filename) = match &self.package {
PackageSource::Ident(PackageIdent::Named(id)) => {
let endpoint = self.env.registry_endpoint()?;
let client = if self.api.token.is_some() {
self.api.client()
} else {
self.api.client_unauthennticated()
}?;

let version = id.version_or_default().to_string();
let version = if version == "*" { None } else { Some(version) };
let version = if version == "*" {
String::from("latest")
} else {
version.to_string()
};
let full_name = id.full_name();
let token = self.env.get_token_opt().map(|x| x.to_string());

let package = wasmer_registry::query_package_from_registry(
endpoint.as_str(),
&full_name,
version.as_deref(),
token.as_deref(),
)
.with_context(|| {
format!(
let rt = tokio::runtime::Runtime::new()?;
let package = rt
.block_on(wasmer_api::query::get_package_version(
&client,
full_name.clone(),
version.clone(),
))?
.with_context(|| {
format!(
"could not retrieve package information for package '{}' from registry '{}'",
full_name, endpoint,
full_name, client.graphql_endpoint(),
)
})?;
})?;

let download_url = package
.pirita_url
.context("registry does provide a container download container download URL")?;
.distribution_v3
.pirita_download_url
.context("registry did not provide a container download URL")?;

let ident = format!("{}@{}", package.package, package.version);
let ident = format!("{}@{}", full_name, package.version);
let filename = if let Some(ns) = &package.package.namespace {
format!(
"{}--{}@{}.webc",
ns.clone(),
package.package.package_name,
package.version
)
} else {
format!("{}@{}.webc", package.package.package_name, package.version)
};

(download_url, token, ident)
(download_url, ident, filename)
}
PackageSource::Ident(PackageIdent::Hash(hash)) => {
let endpoint = self.env.registry_endpoint()?;
let token = self.env.get_token_opt().map(|x| x.to_string());

let client = wasmer_api::WasmerClient::new(endpoint, "wasmer-cli")?;
let client = if let Some(token) = &token {
client.with_auth_token(token.clone())
let client = if self.api.token.is_some() {
self.api.client()
} else {
client
};
self.api.client_unauthennticated()
}?;

let rt = tokio::runtime::Runtime::new()?;
let pkg = rt.block_on(wasmer_api::query::get_package_release(&client, &hash.to_string()))?
.with_context(|| format!("Package with {hash} does not exist in the registry, or is not accessible"))?;

let ident = hash.to_string();
let filename = format!("{}.webc", hash);

(pkg.webc_url, token, ident)
(pkg.webc_url, ident, filename)
}
PackageSource::Path(p) => bail!("cannot download a package from a local path: '{p}'"),
PackageSource::Url(url) => bail!("cannot download a package from a URL: '{}'", url),
Expand All @@ -152,12 +173,9 @@ impl PackageDownload {
};
let client = builder.build().context("failed to create reqwest client")?;

let mut b = client
let b = client
.get(download_url)
.header(http::header::ACCEPT, "application/webc");
if let Some(token) = token {
b = b.header(http::header::AUTHORIZATION, format!("Bearer {token}"));
};

pb.println(format!(
"{} {}Downloading package {} ...",
Expand Down Expand Up @@ -190,7 +208,11 @@ impl PackageDownload {
// Set the length of the progress bar
pb.set_length(webc_total_size);

let mut tmpfile = NamedTempFile::new_in(self.out_path.parent().unwrap())?;
let mut tmpfile = if let Some(parent) = self.out_path.as_ref().and_then(|p| p.parent()) {
NamedTempFile::new_in(parent)?
} else {
NamedTempFile::new()?
};
let accepted_contenttypes = vec![
"application/webc",
"application/octet-stream",
Expand Down Expand Up @@ -231,10 +253,16 @@ impl PackageDownload {
.context("could not parse downloaded file as a package - invalid download?")?;
}

tmpfile.persist(&self.out_path).with_context(|| {
let out_path = if let Some(out_path) = &self.out_path {
out_path.clone()
} else {
current_dir()?.join(filename)
};

tmpfile.persist(&out_path).with_context(|| {
format!(
"could not persist temporary file to '{}'",
self.out_path.display()
out_path.display()
)
})?;

Expand All @@ -244,7 +272,7 @@ impl PackageDownload {
.bold()
.dim(),
WRITING_PACKAGE_EMOJI,
self.out_path.display()
out_path.display()
));

// We're done, so finish the progress bar
Expand All @@ -256,9 +284,8 @@ impl PackageDownload {

#[cfg(test)]
mod tests {
use wasmer_registry::wasmer_env::WASMER_DIR;

use super::*;
use std::str::FromStr;

/// Download a package from the dev registry.
#[test]
Expand All @@ -268,9 +295,13 @@ mod tests {
let out_path = dir.path().join("hello.webc");

let cmd = PackageDownload {
env: WasmerEnv::new(WASMER_DIR.clone(), Some("wasmer.wtf".into()), None, None),
env: WasmerEnv::default(),
api: ApiOpts {
token: None,
registry: Some(url::Url::from_str("https://registry.wasmer.io/graphql").unwrap()),
},
validate: true,
out_path: out_path.clone(),
out_path: Some(out_path.clone()),
package: "wasmer/[email protected]".parse().unwrap(),
quiet: true,
};
Expand Down
Loading