wasmer_wasix/runners/dcgi/
runner.rs1use std::{net::SocketAddr, sync::Arc};
2
3use anyhow::Error;
4use wasmer_journal::FilteredJournalBuilder;
5use wcgi_host::CgiDialect;
6use webc::metadata::Command;
7
8use crate::{
9 Runtime,
10 bin_factory::BinaryPackage,
11 capabilities::Capabilities,
12 journal::DynJournal,
13 runners::{
14 MappedDirectory,
15 dcgi::handler::Handler,
16 wcgi::{self, NoOpWcgiCallbacks, WcgiRunner},
17 },
18 runtime::{DynRuntime, OverriddenRuntime},
19};
20
21use super::{DcgiCallbacks, DcgiInstanceFactory};
22
23#[derive(Debug)]
24pub struct DcgiRunner {
25 config: Config,
26 inner: wcgi::WcgiRunner,
27}
28
29impl DcgiRunner {
30 pub fn new(factory: DcgiInstanceFactory) -> Self {
31 let callbacks = DcgiCallbacks::new(factory, NoOpWcgiCallbacks);
32 DcgiRunner {
33 config: Config {
34 inner: wcgi::Config::new(callbacks.clone()),
35 },
36 inner: WcgiRunner::new(callbacks),
37 }
38 }
39
40 pub fn config(&mut self) -> &mut Config {
41 &mut self.config
42 }
43
44 #[tracing::instrument(skip_all)]
45 fn prepare_handler(
46 &mut self,
47 command_name: &str,
48 pkg: &BinaryPackage,
49 runtime: Arc<dyn Runtime + Send + Sync>,
50 ) -> Result<Handler, Error> {
51 let inner: wcgi::Handler =
52 self.inner
53 .prepare_handler(command_name, pkg, true, CgiDialect::Rfc3875, runtime)?;
54 Ok(Handler::new(inner))
55 }
56}
57
58pub const DCGI_RUNNER_URI: &str = "https://webc.org/runner/dcgi";
60
61impl crate::runners::Runner for DcgiRunner {
62 fn can_run_command(command: &Command) -> Result<bool, Error> {
63 Ok(command.runner.starts_with(DCGI_RUNNER_URI))
64 }
65
66 fn run_command(
67 &mut self,
68 command_name: &str,
69 pkg: &BinaryPackage,
70 runtime: Arc<DynRuntime>,
71 ) -> Result<(), Error> {
72 let journals = runtime
77 .writable_journals()
78 .map(|journal| {
79 let journal = FilteredJournalBuilder::new()
80 .with_ignore_memory(true)
81 .with_ignore_threads(true)
82 .with_ignore_core(true)
83 .with_ignore_snapshots(true)
84 .with_ignore_networking(true)
85 .with_ignore_stdio(true)
86 .build(journal);
87 Arc::new(journal) as Arc<DynJournal>
88 })
89 .collect::<Vec<_>>();
90 let runtime = OverriddenRuntime::new(runtime).with_writable_journals(journals);
91 let runtime = Arc::new(runtime) as Arc<DynRuntime>;
92
93 let handler = self.prepare_handler(command_name, pkg, Arc::clone(&runtime))?;
95 self.inner.run_command_with_handler(handler, runtime)
96 }
97}
98
99#[derive(Debug)]
100pub struct Config {
101 inner: wcgi::Config,
102}
103
104impl Config {
105 pub fn inner(&mut self) -> &mut wcgi::Config {
106 &mut self.inner
107 }
108
109 pub fn addr(&mut self, addr: SocketAddr) -> &mut Self {
110 self.inner.addr(addr);
111 self
112 }
113
114 pub fn arg(&mut self, arg: impl Into<String>) -> &mut Self {
116 self.inner.arg(arg);
117 self
118 }
119
120 pub fn args<A, S>(&mut self, args: A) -> &mut Self
122 where
123 A: IntoIterator<Item = S>,
124 S: Into<String>,
125 {
126 self.inner.args(args);
127 self
128 }
129
130 pub fn env(&mut self, name: impl Into<String>, value: impl Into<String>) -> &mut Self {
132 self.inner.env(name, value);
133 self
134 }
135
136 pub fn envs<I, K, V>(&mut self, variables: I) -> &mut Self
138 where
139 I: IntoIterator<Item = (K, V)>,
140 K: Into<String>,
141 V: Into<String>,
142 {
143 self.inner.envs(variables);
144 self
145 }
146
147 pub fn forward_host_env(&mut self) -> &mut Self {
149 self.inner.forward_host_env();
150 self
151 }
152
153 pub fn map_directory(&mut self, dir: MappedDirectory) -> &mut Self {
154 self.inner.map_directory(dir);
155 self
156 }
157
158 pub fn map_directories(
159 &mut self,
160 mappings: impl IntoIterator<Item = MappedDirectory>,
161 ) -> &mut Self {
162 self.inner.map_directories(mappings);
163 self
164 }
165
166 pub fn callbacks(&mut self, callbacks: impl wcgi::Callbacks + 'static) -> &mut Self {
169 self.inner.callbacks(callbacks);
170 self
171 }
172
173 pub fn inject_package(&mut self, pkg: BinaryPackage) -> &mut Self {
175 self.inner.inject_package(pkg);
176 self
177 }
178
179 pub fn inject_packages(
181 &mut self,
182 packages: impl IntoIterator<Item = BinaryPackage>,
183 ) -> &mut Self {
184 self.inner.inject_packages(packages);
185 self
186 }
187
188 pub fn capabilities(&mut self) -> &mut Capabilities {
189 self.inner.capabilities()
190 }
191
192 #[cfg(feature = "journal")]
193 pub fn add_snapshot_trigger(&mut self, on: crate::journal::SnapshotTrigger) {
194 self.inner.add_snapshot_trigger(on);
195 }
196
197 #[cfg(feature = "journal")]
198 pub fn add_default_snapshot_triggers(&mut self) -> &mut Self {
199 self.inner.add_default_snapshot_triggers();
200 self
201 }
202
203 #[cfg(feature = "journal")]
204 pub fn has_snapshot_trigger(&self, on: crate::journal::SnapshotTrigger) -> bool {
205 self.inner.has_snapshot_trigger(on)
206 }
207
208 #[cfg(feature = "journal")]
209 pub fn with_snapshot_interval(&mut self, period: std::time::Duration) -> &mut Self {
210 self.inner.with_snapshot_interval(period);
211 self
212 }
213
214 #[cfg(feature = "journal")]
215 pub fn with_stop_running_after_snapshot(&mut self, stop_running: bool) {
216 self.inner.with_stop_running_after_snapshot(stop_running);
217 }
218
219 #[cfg(feature = "journal")]
220 pub fn add_read_only_journal(
221 &mut self,
222 journal: Arc<crate::journal::DynReadableJournal>,
223 ) -> &mut Self {
224 self.inner.add_read_only_journal(journal);
225 self
226 }
227
228 #[cfg(feature = "journal")]
229 pub fn add_writable_journal(&mut self, journal: Arc<crate::journal::DynJournal>) -> &mut Self {
230 self.inner.add_writable_journal(journal);
231 self
232 }
233}
234
235#[cfg(test)]
236mod tests {
237 use super::*;
238
239 #[test]
240 fn send_and_sync() {
241 fn assert_send<T: Send>() {}
242 fn assert_sync<T: Sync>() {}
243
244 assert_send::<DcgiRunner>();
245 assert_sync::<DcgiRunner>();
246 }
247}