From 77eee644c9c9bf6e3c19a5c6efb9d31f5d91318e Mon Sep 17 00:00:00 2001 From: Tyler Murphy Date: Sun, 2 Jul 2023 22:40:04 -0400 Subject: [PATCH] move body to stdin --- README.md | 6 +++--- examples/body.sh | 4 ++-- examples/command.sh | 3 +-- src/script.rs | 27 +++++++++++++++++++++------ src/server.rs | 2 +- 5 files changed, 28 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 8ba0773..e6b7580 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ printf "joe\n" exit 200 ``` -Finally if you wish to read the request body given by the user, that is always stored in argument 1. For example to create a echo endpoint: +Finally if you wish to read the request body given by the user, that is always stored in stdin. For example to create a echo endpoint: ```sh #!/bin/bash @@ -46,8 +46,8 @@ Finally if you wish to read the request body given by the user, that is always s # we still need to tell there will be no more headers printf "\n" -# the body of any http request made will be stored in argument 1 -printf "$1" +# the body of any http request made will be stored in stdin +cat exit 200 ``` diff --git a/examples/body.sh b/examples/body.sh index 5c56df2..bf671df 100755 --- a/examples/body.sh +++ b/examples/body.sh @@ -4,7 +4,7 @@ # we still need to tell there will be no more headers printf "\n" -# the body of any http request made will be stored in argument 1 -printf "$1" +# the body of any http request made will be stored in stdin +cat exit 200 diff --git a/examples/command.sh b/examples/command.sh index 52a5666..64e159b 100755 --- a/examples/command.sh +++ b/examples/command.sh @@ -6,6 +6,5 @@ printf "\n" neofetch -# return http code 418 im a teapot -exit 418 +exit 200 diff --git a/src/script.rs b/src/script.rs index 369fbf8..4a94ba4 100644 --- a/src/script.rs +++ b/src/script.rs @@ -1,6 +1,8 @@ -use std::{env, collections::HashMap, fs::read_to_string, process::Command, result::Result, error::Error}; +use std::{env, collections::HashMap, process::Stdio, fs::read_to_string, result::Result, error::Error}; +use tokio::process::Command; +use tokio::io::AsyncWriteExt; -use crate::http::{response::Response, method::Method}; +use crate::http::{response::Response, method::Method, header::Header}; pub struct Script { path: String @@ -11,17 +13,28 @@ impl Script { Self { path } } - pub fn run(&self, body: Option<&String>) -> Result { + pub async fn run(&self, body: Option<&String>) -> Result { let mut res = Response::new(); let mut command = Command::new(&self.path); + command.stdin(Stdio::piped()); + command.stdout(Stdio::piped()); + + let mut child = match command.spawn() { + Ok(child) => child, + Err(err) => return Err(format!("{err}")) + }; + if let Some(body) = body { - command.args([body]); + let Some(mut stdin) = child.stdin.take() else { + return Err("failed to read stdin".into()) + }; + let _ = stdin.write(body.as_bytes()).await; } - let output = match command.output() { + let output = match child.wait_with_output().await { Ok(output) => output, - Err(err) => return Err(err) + Err(err) => return Err(format!("{err}")) }; let status = output.status.code().unwrap_or(500) as u16; @@ -32,6 +45,8 @@ impl Script { res.headers.serialize(&mut lines); let body: String = lines.collect::>().join("\n"); + res.headers.put(Header::new("Content-Length", &format!("{}", body.len()))); + if body.len() > 0 { res.body = Some(body); } diff --git a/src/server.rs b/src/server.rs index 4b1f2b3..1d8193f 100644 --- a/src/server.rs +++ b/src/server.rs @@ -38,7 +38,7 @@ pub async fn handle_connection(mut socket: TcpStream, config: Arc) { return }; - match script.run(req.body.as_ref()) { + match script.run(req.body.as_ref()).await { Ok(res) => { let res_str = res.deserialize(); let _ = socket.write(res_str.as_bytes()).await;