Skip to content

Commit

Permalink
Add a package.metadata.component.proxy setting. (#221)
Browse files Browse the repository at this point in the history
This commit adds a `package.metadata.component.proxy` setting to `Cargo.toml`
that controls whether or not to use the `wasi:http/proxy` specific adapter.

This option can be set when creating a project with `cargo component new --lib
--proxy`.

The `wasi:http/proxy` adapter is now built-in to `cargo-component`; it adapters
from preview1 in a way that ensures the resulting component conforms to the
`wasi:http/proxy` world.

Additionally, the `--command` option has been renamed to `--bin`, with an alias
for `--command` for backwards compatibility.
  • Loading branch information
peterhuene authored Jan 26, 2024
1 parent b8858b8 commit c2f294d
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 6 deletions.
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ wasmparser = { workspace = true }
wat = { workspace = true }
warg-server = { workspace = true }
tempfile = { workspace = true }
wasmprinter = { workspace = true }

[workspace]
members = ["crates/core", "crates/wit"]
Expand Down Expand Up @@ -104,3 +105,4 @@ predicates = "3.1.0"
wasmparser = "0.120.0"
wat = "1.0.84"
warg-server = "0.2.0"
wasmprinter = "0.2.77"
Binary file not shown.
14 changes: 11 additions & 3 deletions src/commands/new.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,17 @@ pub struct NewCommand {
pub vcs: Option<String>,

/// Create a CLI command component [default]
#[clap(long = "command", conflicts_with("lib"))]
pub command: bool,
#[clap(long = "bin", alias = "command", conflicts_with = "lib")]
pub bin: bool,

/// Create a library (reactor) component
#[clap(long = "lib", alias = "reactor")]
pub lib: bool,

/// Use the built-in `wasi:http/proxy` module adapter
#[clap(long = "proxy", requires = "lib")]
pub proxy: bool,

/// Edition to set for the generated crate
#[clap(long = "edition", value_name = "YEAR", value_parser = ["2015", "2018", "2021"])]
pub edition: Option<String>,
Expand Down Expand Up @@ -277,6 +281,10 @@ impl NewCommand {
component["registries"] = Item::Table(table);
}

if self.proxy {
component["proxy"] = value(true);
}

let mut metadata = Table::new();
metadata.set_implicit(true);
metadata.set_position(doc.len());
Expand Down Expand Up @@ -315,7 +323,7 @@ impl NewCommand {
}

fn is_command(&self) -> bool {
self.command || !self.lib
self.bin || !self.lib
}

fn generate_source(
Expand Down
29 changes: 27 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -606,8 +606,18 @@ async fn generate_package_bindings(
Ok(())
}

fn adapter_bytes(metadata: &ComponentMetadata, binary: bool) -> Result<Cow<[u8]>> {
fn adapter_bytes<'a>(
config: &Config,
metadata: &'a ComponentMetadata,
binary: bool,
) -> Result<Cow<'a, [u8]>> {
if let Some(adapter) = &metadata.section.adapter {
if metadata.section.proxy {
config.terminal().warn(
"ignoring `proxy` setting due to `adapter` setting being present in `Cargo.toml`",
)?;
}

return Ok(fs::read(adapter)
.with_context(|| {
format!(
Expand All @@ -619,11 +629,23 @@ fn adapter_bytes(metadata: &ComponentMetadata, binary: bool) -> Result<Cow<[u8]>
}

if binary {
if metadata.section.proxy {
config
.terminal()
.warn("ignoring `proxy` setting in `Cargo.toml` for command component")?;
}

Ok(Cow::Borrowed(include_bytes!(concat!(
"../adapters/",
env!("WASI_ADAPTER_VERSION"),
"/wasi_snapshot_preview1.command.wasm"
))))
} else if metadata.section.proxy {
Ok(Cow::Borrowed(include_bytes!(concat!(
"../adapters/",
env!("WASI_ADAPTER_VERSION"),
"/wasi_snapshot_preview1.proxy.wasm"
))))
} else {
Ok(Cow::Borrowed(include_bytes!(concat!(
"../adapters/",
Expand Down Expand Up @@ -663,7 +685,10 @@ fn create_component(

let encoder = ComponentEncoder::default()
.module(&module)?
.adapter("wasi_snapshot_preview1", &adapter_bytes(metadata, binary)?)
.adapter(
"wasi_snapshot_preview1",
&adapter_bytes(config, metadata, binary)?,
)
.with_context(|| {
format!(
"failed to load adapter module `{path}`",
Expand Down
4 changes: 4 additions & 0 deletions src/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,10 @@ pub struct ComponentSection {
pub registries: HashMap<String, Url>,
/// The configuration for bindings generation.
pub bindings: Bindings,
/// Whether to use the built-in `wasi:http/proxy` adapter for the component.
///
/// This should only be `true` when `adapter` is None.
pub proxy: bool,
}

/// Represents cargo metadata for a WebAssembly component.
Expand Down
64 changes: 64 additions & 0 deletions tests/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -834,3 +834,67 @@ fn it_builds_with_versioned_wit() -> Result<()> {

Ok(())
}

#[test]
fn it_warns_on_proxy_setting_for_command() -> Result<()> {
let project = Project::new_bin("foo")?;
project.update_manifest(|mut doc| {
doc["package"]["metadata"]["component"]["proxy"] = value(true);
Ok(doc)
})?;

project
.cargo_component("build")
.assert()
.stderr(contains(
"warning: ignoring `proxy` setting in `Cargo.toml` for command component",
))
.success();

validate_component(&project.debug_wasm("foo"))?;

Ok(())
}

#[test]
fn it_warns_with_proxy_and_adapter_settings() -> Result<()> {
let project = Project::new("foo")?;
project.update_manifest(|mut doc| {
doc["package"]["metadata"]["component"]["proxy"] = value(true);
doc["package"]["metadata"]["component"]["adapter"] =
value(adapter_path().to_str().unwrap());
Ok(doc)
})?;

project
.cargo_component("build")
.assert()
.stderr(contains("warning: ignoring `proxy` setting due to `adapter` setting being present in `Cargo.toml`"))
.success();

validate_component(&project.debug_wasm("foo"))?;

Ok(())
}

#[test]
fn it_builds_with_proxy_adapter() -> Result<()> {
let dir = Rc::new(TempDir::new()?);
let project = Project::with_dir(dir.clone(), "foo", "--proxy")?;

project
.cargo_component("build")
.assert()
.stderr(contains("Finished dev [unoptimized + debuginfo] target(s)"))
.success();

validate_component(&project.debug_wasm("foo"))?;

let text = wasmprinter::print_file(project.debug_wasm("foo"))?;
assert!(
!text.contains("wasi:cli/environment"),
"proxy wasm should have no reference to `wasi:cli/environment`"
);

Ok(())
}
28 changes: 27 additions & 1 deletion tests/new.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ fn help() {
fn it_creates_the_expected_files_for_bin() -> Result<()> {
let dir = TempDir::new()?;

cargo_component("new --command foo")
cargo_component("new --bin foo")
.current_dir(dir.path())
.assert()
.stderr(contains("Updated manifest of package `foo"))
Expand Down Expand Up @@ -179,6 +179,18 @@ async fn it_errors_if_target_does_not_exist() -> Result<()> {
Ok(())
}

#[test]
fn it_supports_the_command_option() -> Result<()> {
let dir = TempDir::new()?;

cargo_component("new --command foo")
.current_dir(dir.path())
.assert()
.try_success()?;

Ok(())
}

#[test]
fn it_supports_the_reactor_option() -> Result<()> {
let dir = TempDir::new()?;
Expand All @@ -190,3 +202,17 @@ fn it_supports_the_reactor_option() -> Result<()> {

Ok(())
}

#[test]
fn it_supports_the_proxy_option() -> Result<()> {
let dir: TempDir = TempDir::new()?;

cargo_component("new --lib --proxy foo")
.current_dir(dir.path())
.assert()
.try_success()?;

assert!(fs::read_to_string(dir.path().join("foo/Cargo.toml"))?.contains("proxy = true"));

Ok(())
}

0 comments on commit c2f294d

Please sign in to comment.