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

Apply CGI environment variables in the correct order #3718

Merged
merged 5 commits into from
Mar 29, 2023
Merged
Show file tree
Hide file tree
Changes from 4 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
16 changes: 11 additions & 5 deletions lib/cli/src/commands/run_unstable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use wasmer::{
use wasmer_cache::Cache;
use wasmer_compiler::ArtifactBuild;
use wasmer_registry::Package;
use wasmer_wasix::runners::{MappedDirectory, Runner, WapmContainer};
use wasmer_wasix::runners::{wcgi::AbortHandle, MappedDirectory, Runner, WapmContainer};
use webc::metadata::Manifest;
use webc_v4::DirOrFile;

Expand Down Expand Up @@ -158,7 +158,7 @@ impl RunUnstable {
.addr(self.wcgi.addr)
.envs(self.wasi.env_vars.clone())
.map_directories(self.wasi.mapped_dirs.clone())
.callbacks(Callbacks::default());
.callbacks(Callbacks::new(self.wcgi.addr));
if self.wasi.forward_host_env {
runner.config().forward_host_env();
}
Expand Down Expand Up @@ -594,17 +594,23 @@ impl Default for WcgiOptions {
#[derive(Debug)]
struct Callbacks {
stderr: Mutex<LineWriter<std::io::Stderr>>,
addr: SocketAddr,
}

impl Default for Callbacks {
fn default() -> Self {
Self {
impl Callbacks {
fn new(addr: SocketAddr) -> Self {
Callbacks {
stderr: Mutex::new(LineWriter::new(std::io::stderr())),
addr,
}
}
}

impl wasmer_wasix::runners::wcgi::Callbacks for Callbacks {
fn started(&self, _abort: AbortHandle) {
println!("WCGI Server running at http://{}/", self.addr);
}

fn on_stderr(&self, raw_message: &[u8]) {
if let Ok(mut stderr) = self.stderr.lock() {
// If the WCGI runner printed any log messages we want to make sure
Expand Down
6 changes: 3 additions & 3 deletions lib/wasi/src/runners/wasi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,9 @@ impl WasiRunner {
program_name: &str,
wasi: &Wasi,
) -> Result<WasiEnvBuilder, anyhow::Error> {
let mut builder =
self.wasi
.prepare_webc_env(container.container_fs(), program_name, wasi)?;
let mut builder = WasiEnvBuilder::new(program_name);
self.wasi
.prepare_webc_env(&mut builder, container.container_fs(), wasi)?;

if let Some(tasks) = &self.tasks {
let rt = PluggableRuntime::new(Arc::clone(tasks));
Expand Down
14 changes: 7 additions & 7 deletions lib/wasi/src/runners/wasi_common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use anyhow::{Context, Error};
use virtual_fs::{FileSystem, OverlayFileSystem, RootFileSystemBuilder};
use webc::metadata::annotations::Wasi as WasiAnnotation;

use crate::{runners::MappedDirectory, WasiEnv, WasiEnvBuilder};
use crate::{runners::MappedDirectory, WasiEnvBuilder};

#[derive(Debug, Default, Clone, serde::Serialize, serde::Deserialize)]
pub(crate) struct CommonWasiOptions {
Expand All @@ -21,11 +21,11 @@ pub(crate) struct CommonWasiOptions {
impl CommonWasiOptions {
pub(crate) fn prepare_webc_env(
&self,
builder: &mut WasiEnvBuilder,
container_fs: Arc<dyn FileSystem>,
program_name: &str,
wasi: &WasiAnnotation,
) -> Result<WasiEnvBuilder, anyhow::Error> {
let mut builder = WasiEnv::builder(program_name).args(&self.args);
) -> Result<(), anyhow::Error> {
builder.add_args(&self.args);

let fs = prepare_filesystem(&self.mapped_dirs, container_fs, |path| {
builder.add_preopen_dir(path).map_err(Error::from)
Expand All @@ -34,10 +34,10 @@ impl CommonWasiOptions {
builder.add_preopen_dir("/")?;
builder.add_preopen_dir(".")?;

self.populate_env(wasi, &mut builder);
self.populate_args(wasi, &mut builder);
self.populate_env(wasi, builder);
self.populate_args(wasi, builder);

Ok(builder)
Ok(())
}

fn populate_env(&self, wasi: &WasiAnnotation, builder: &mut WasiEnvBuilder) {
Expand Down
21 changes: 13 additions & 8 deletions lib/wasi/src/runners/wcgi/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,19 +39,21 @@ impl Handler {

tracing::debug!("Creating the WebAssembly instance");

let mut request_specific_env = HashMap::new();
let mut builder = WasiEnvBuilder::new(&self.program_name);

if self.dialect == CgiDialect::Rfc3875 {
// HACK(Michael-F-Bryan): this belongs in the wcgi-host crate
request_specific_env.insert("SCRIPT_NAME".to_string(), parts.uri.to_string());
}
// Note: We want to apply the CGI environment variables *before*
// anything specified by WASI annotations so users get a chance to
// override things like $DOCUMENT_ROOT and $SCRIPT_FILENAME.
let mut request_specific_env = HashMap::new();
self.dialect
.prepare_environment_variables(parts, &mut request_specific_env);
builder.add_envs(request_specific_env);

(self.setup_builder)(&mut builder)?;

let rt = PluggableRuntime::new(Arc::clone(&self.task_manager));

let builder = (self.setup_builder)()?
.envs(request_specific_env)
let builder = builder
.stdin(Box::new(req_body_receiver))
.stdout(Box::new(res_body_sender))
.stderr(Box::new(stderr_sender))
Expand Down Expand Up @@ -205,13 +207,16 @@ async fn consume_stderr(
}
}

type SetupBuilder = Box<dyn Fn(&mut WasiEnvBuilder) -> Result<(), anyhow::Error> + Send + Sync>;

#[derive(derivative::Derivative)]
#[derivative(Debug)]
pub(crate) struct SharedState {
pub(crate) module: Module,
pub(crate) dialect: CgiDialect,
pub(crate) program_name: String,
#[derivative(Debug = "ignore")]
pub(crate) setup_builder: Box<dyn Fn() -> Result<WasiEnvBuilder, anyhow::Error> + Send + Sync>,
pub(crate) setup_builder: SetupBuilder,
#[derivative(Debug = "ignore")]
pub(crate) callbacks: Arc<dyn Callbacks>,
#[derivative(Debug = "ignore")]
Expand Down
1 change: 1 addition & 0 deletions lib/wasi/src/runners/wcgi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ mod handler;
mod runner;

pub use self::runner::{Callbacks, Config, WcgiRunner};
pub use futures::future::AbortHandle;
19 changes: 9 additions & 10 deletions lib/wasi/src/runners/wcgi/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,15 +138,16 @@ impl WcgiRunner {
};

let shared = SharedState {
module,
dialect,
program_name: self.program_name.clone(),
setup_builder: Box::new(self.setup_builder(ctx, wasi)),
callbacks: Arc::clone(&self.config.callbacks),
task_manager: self
.config
.task_manager
.clone()
.unwrap_or_else(|| Arc::new(TokioTaskManager::default())),
module,
dialect,
callbacks: Arc::clone(&self.config.callbacks),
setup_builder: Box::new(self.setup_builder(ctx, wasi)),
};

Ok(Handler::new(shared))
Expand All @@ -156,23 +157,21 @@ impl WcgiRunner {
&self,
ctx: &RunnerContext<'_>,
wasi: &Wasi,
) -> impl Fn() -> Result<WasiEnvBuilder, Error> + Send + Sync {
) -> impl Fn(&mut WasiEnvBuilder) -> Result<(), Error> + Send + Sync {
let container_fs = ctx.container_fs();
let wasi_common = self.config.wasi.clone();
let program_name = self.program_name.clone();
let wasi = wasi.clone();
let tasks = self.config.task_manager.clone();

move || {
let mut builder =
wasi_common.prepare_webc_env(Arc::clone(&container_fs), &program_name, &wasi)?;
move |builder| {
wasi_common.prepare_webc_env(builder, Arc::clone(&container_fs), &wasi)?;

if let Some(tasks) = &tasks {
let rt = PluggableRuntime::new(Arc::clone(tasks));
builder.set_runtime(Arc::new(rt));
}

Ok(builder)
Ok(())
}
}
}
Expand Down