diff --git a/examples/debug.cgi b/examples/debug.cgi index bdd8ceff..8cd0c0e8 100755 --- a/examples/debug.cgi +++ b/examples/debug.cgi @@ -10,3 +10,5 @@ p ARGV puts "STDIN:" p STDIN.read + +STDERR.puts "Done" diff --git a/src/cgi.rs b/src/cgi.rs new file mode 100644 index 00000000..badc8d65 --- /dev/null +++ b/src/cgi.rs @@ -0,0 +1,30 @@ +use std::process::{Command, Stdio}; +use std::io::Write; +use std::path::PathBuf; + +pub fn run(script: &PathBuf) { + println!("Running script {}...",script.display()); + + let mut child = Command::new(script) + .arg("-test") + .arg("echo hello") + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .spawn() + .expect("failed to start script {script}"); + + let mut stdin = child.stdin.take().expect("Failed to open stdin"); + + std::thread::spawn(move || { + stdin.write_all("Hello, world!".as_bytes()).expect("Failed to write to stdin"); + }); + + let output = child.wait_with_output().expect("Failed to read stdout"); + + let stdout = String::from_utf8_lossy(&output.stdout); + let stderr = String::from_utf8_lossy(&output.stderr); + + println!("Exit code: {}", output.status); + println!("STDOUT: {stdout}"); + println!("STDERR: {stderr}"); +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 9208125a..2fa2d0c6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ use clap::{Parser, Subcommand}; use std::path::PathBuf; +mod cgi; mod server; #[derive(Parser)] @@ -21,6 +22,12 @@ enum Commands { #[arg(short, long, value_name = "SCRIPT")] script: PathBuf, }, + /// Tests a CGI script. + Test { + /// Sets a CGI script file + #[arg(short, long, value_name = "SCRIPT")] + script: PathBuf, + }, } pub fn main() { @@ -30,15 +37,21 @@ pub fn main() { // You can check for the existence of subcommands, and if found use their // matches just as you would the top level cmd - if let Some(Commands::Serve { script }) = &options.command { - // Configure a runtime for the server that runs everything on the current thread - let rt = tokio::runtime::Builder::new_current_thread() - .enable_all() - .build() - .expect("build runtime"); - - // Combine it with a `LocalSet, which means it can spawn !Send futures... - let local = tokio::task::LocalSet::new(); - local.block_on(&rt, server::serve(script)).unwrap(); + match &options.command { + Some(Commands::Serve { script }) => { + // Configure a runtime for the server that runs everything on the current thread + let rt = tokio::runtime::Builder::new_current_thread() + .enable_all() + .build() + .expect("build runtime"); + + // Combine it with a `LocalSet, which means it can spawn !Send futures... + let local = tokio::task::LocalSet::new(); + local.block_on(&rt, server::serve(script)).unwrap(); + } + Some(Commands::Test { script }) => { + cgi::run(script); + } + _ => {} } } diff --git a/src/server.rs b/src/server.rs index 9c9a8650..2229ba81 100644 --- a/src/server.rs +++ b/src/server.rs @@ -13,6 +13,7 @@ use tokio::net::TcpListener; use tokio::pin; async fn hello(_: Request) -> Result>, Infallible> { + Ok(Response::new(Full::new(Bytes::from("Hello, World!")))) }