Skip to content

Commit

Permalink
Move the wcgi-runner crate into the Wasmer repo
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael-F-Bryan committed Feb 22, 2023
1 parent b42cd59 commit 95a3a2d
Show file tree
Hide file tree
Showing 17 changed files with 1,633 additions and 21 deletions.
291 changes: 279 additions & 12 deletions Cargo.lock

Large diffs are not rendered by default.

18 changes: 9 additions & 9 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ autoexamples = false

[dependencies]
wasmer = { version = "=3.2.0-alpha.1", path = "lib/api", default-features = false }
wasmer-compiler = { version = "=3.2.0-alpha.1", path = "lib/compiler", features = ["compiler"] }
wasmer-compiler = { version = "=3.2.0-alpha.1", path = "lib/compiler", features = [
"compiler",
] }
wasmer-compiler-cranelift = { version = "=3.2.0-alpha.1", path = "lib/compiler-cranelift", optional = true }
wasmer-compiler-singlepass = { version = "=3.2.0-alpha.1", path = "lib/compiler-singlepass", optional = true }
wasmer-compiler-llvm = { version = "=3.2.0-alpha.1", path = "lib/compiler-llvm", optional = true }
Expand Down Expand Up @@ -50,6 +52,7 @@ members = [
"lib/wasi-local-networking",
"lib/wasix/wasix-http-client",
"lib/wasm-interface",
"lib/wcgi-runner",
"lib/c-api/tests/wasmer-c-api-test-runner",
"lib/c-api/examples/wasmer-capi-examples-runner",
"lib/types",
Expand All @@ -71,7 +74,9 @@ glob = "0.3"
rustc_version = "0.4"

[dev-dependencies]
wasmer = { version = "=3.2.0-alpha.1", path = "lib/api", default-features = false, features = ["cranelift"] }
wasmer = { version = "=3.2.0-alpha.1", path = "lib/api", default-features = false, features = [
"cranelift",
] }
anyhow = "1.0"
criterion = "0.3"
lazy_static = "1.4"
Expand Down Expand Up @@ -105,10 +110,7 @@ wast = ["wasmer-wast"]
wasi = ["wasmer-wasi"]
emscripten = ["wasmer-emscripten"]
wat = ["wasmer/wat"]
compiler = [
"wasmer/compiler",
"wasmer-compiler/translator",
]
compiler = ["wasmer/compiler", "wasmer-compiler/translator"]
singlepass = ["wasmer-compiler-singlepass", "compiler"]
cranelift = ["wasmer-compiler-cranelift", "compiler"]
llvm = ["wasmer-compiler-llvm", "compiler"]
Expand All @@ -123,9 +125,7 @@ test-singlepass = ["singlepass"]
test-cranelift = ["cranelift"]
test-llvm = ["llvm"]

test-universal = [
"test-generator/test-universal",
]
test-universal = ["test-generator/test-universal"]

# Specifies that we're running in coverage testing mode. This disables tests
# that raise signals because that interferes with tarpaulin.
Expand Down
47 changes: 47 additions & 0 deletions lib/wcgi-runner/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
[package]
name = "wcgi-runner"
version = "3.2.0-alpha.1"
description = "A runner that can serve WCGI programs locally"
authors = ["Wasmer Engineering Team <[email protected]>"]
repository = "https://github.com/wasmerio/wasmer"
license = "MIT"
readme = "README.md"
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
anyhow = { version = "1", features = ["backtrace"] }
async-trait = "0.1.64"
bytes = "1.4.0"
clap = { version = "4", features = ["derive", "env"] }
futures = "0.3.25"
http = "0.2.8"
hyper = { version = "0.14.23", features = ["server", "stream"] }
md5 = "0.7.0"
serde = { version = "1.0.152", features = ["derive"] }
serde_cbor = "0.11.2"
thiserror = "1.0.38"
tiny_http = "0.12.0"
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
tower-service = "0.3"
tracing = "0.1.37"
tracing-subscriber = { version = "0.3.16", features = ["fmt", "env-filter"] }
wasmer = { version = "3.2.0-alpha.1", path = "../api", default-features = false, features = [
"sys",
"cranelift",
"singlepass",
] }
wasmer-wasi = { version = "3.2.0-alpha.1", path = "../wasi", features = [
"sys-default",
], default-features = false }
wasmer-vfs = { version = "3.2.0-alpha.1", path = "../vfs", default-features = false }
wcgi = { version = "0.1.1" }
wcgi-host = { version = "0.1.0" }
webc = { version = "5.0.0-rc.1", default-features = false }

[dev-dependencies]
reqwest = { version = "0.11.0", default-features = false, features = [
"rustls-tls",
] }
ureq = "2.6.2"
9 changes: 9 additions & 0 deletions lib/wcgi-runner/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# wcgi-runner

A server that can serve [wcgi][wcgi] web servers.

## Usage

`wcgi-runner --watch ./path/to/module.wasm`

[wcgi]: https://github.com/wasmerio/wcgi
24 changes: 24 additions & 0 deletions lib/wcgi-runner/src/annotations.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use wcgi_host::CgiDialect;

// FIXME(@Michael-F-Bryan): Make this public in the webc crate
#[derive(Debug, Default, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub struct WasiCommandAnnotation {
#[serde(default)]
pub atom: Option<String>,
#[serde(default)]
pub package: Option<String>,
#[serde(default)]
pub env: Option<Vec<String>>,
#[serde(default)]
pub main_args: Option<Vec<String>>,
#[serde(default, rename = "mountAtomInVolume")]
pub mount_atom_in_volume: Option<String>,
}

// FIXME(@Michael-F-Bryan): Add this to the webc crate and update
// wapm-targz-to-pirita
#[derive(Debug, Default, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub struct WcgiAnnotation {
#[serde(default)]
pub dialect: Option<CgiDialect>,
}
111 changes: 111 additions & 0 deletions lib/wcgi-runner/src/bin/wcgi-runner.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
use std::{convert::Infallible, net::SocketAddr, path::PathBuf};

use anyhow::{Context, Error};
use clap::Parser;
use tracing_subscriber::fmt::format::FmtSpan;
use wcgi_runner::Runner;

fn main() -> Result<(), Error> {
if std::env::var("RUST_LOG").is_err() {
std::env::set_var("RUST_LOG", "wcgi_runner=trace,info");
}
tracing_subscriber::fmt()
.with_span_events(FmtSpan::CLOSE)
.init();

let Args {
address,
input,
env_all,
mapped_dirs,
} = Args::parse();

// Hack to initialize the global shared tokio task manager handle.
// Prevents "cannot drop runtime in async context" errors, because
// the default will be initialized to the current tokio context.
let rt = wasmer_wasi::runtime::task_manager::tokio::TokioTaskManager::default();

let mut builder = Runner::builder()
.map_dirs(mapped_dirs)
.tokio_handle(rt.runtime_handle());

if env_all {
builder = builder.forward_host_env();
}

let runner = builder
.watch(input)
.context("Unable to create the runner")?;

let make_service = hyper::service::make_service_fn(move |_| {
let runner = runner.clone();
async move { Ok::<_, Infallible>(runner) }
});

tracing::info!(%address, "Started the server");
rt.runtime_handle()
.block_on(async { hyper::Server::bind(&address).serve(make_service).await })
.context("Unable to start the server")?;

Ok(())
}

#[derive(Debug, Clone, Parser)]
#[clap(about, version, author)]
struct Args {
/// Server address.
#[clap(long, short, env, default_value_t = ([127, 0, 0, 1], 8000).into())]
address: SocketAddr,

/// Map a host directory to a different location for the Wasm module
///
/// Example:
///
/// --map-dir /www:./my-website
/// => will make the ./my-website directory available for wazsm at /www
#[clap(
long = "mapdir",
name = "GUEST_DIR:HOST_DIR",
value_parser = parse_mapdir,
)]
mapped_dirs: Vec<(String, PathBuf)>,

/// Forward all host env variables to the wcgi task.
#[clap(long)]
env_all: bool,

/// A WCGI program.
input: PathBuf,
}

/// Parses a mapdir from a string
// NOTE: copied from wasmerio/wasmer lib/cli/src/utils.rs.
pub fn parse_mapdir(entry: &str) -> Result<(String, PathBuf), anyhow::Error> {
fn retrieve_alias_pathbuf(
alias: &str,
real_dir: &str,
) -> Result<(String, PathBuf), anyhow::Error> {
let pb = PathBuf::from(&real_dir);
if let Ok(pb_metadata) = pb.metadata() {
if !pb_metadata.is_dir() {
anyhow::bail!("\"{real_dir}\" exists, but it is not a directory");
}
} else {
anyhow::bail!("Directory \"{real_dir}\" does not exist");
}
Ok((alias.to_string(), pb))
}

// We try first splitting by `::`
if let Some((alias, real_dir)) = entry.split_once("::") {
retrieve_alias_pathbuf(alias, real_dir)
}
// And then we try splitting by `:` (for compatibility with previous API)
else if let Some((alias, real_dir)) = entry.split_once(':') {
retrieve_alias_pathbuf(alias, real_dir)
} else {
anyhow::bail!(
"Directory mappings must consist of two paths separate by a `::` or `:`. Found {entry}",
)
}
}
Loading

0 comments on commit 95a3a2d

Please sign in to comment.