move body to stdin

This commit is contained in:
Murphy 2023-07-02 22:40:04 -04:00
parent 41fe16978e
commit 77eee644c9
5 changed files with 28 additions and 14 deletions

View file

@ -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
```

View file

@ -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

View file

@ -6,6 +6,5 @@ printf "\n"
neofetch
# return http code 418 im a teapot
exit 418
exit 200

View file

@ -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<Response, std::io::Error> {
pub async fn run(&self, body: Option<&String>) -> Result<Response, String> {
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::<Vec<&str>>().join("\n");
res.headers.put(Header::new("Content-Length", &format!("{}", body.len())));
if body.len() > 0 {
res.body = Some(body);
}

View file

@ -38,7 +38,7 @@ pub async fn handle_connection(mut socket: TcpStream, config: Arc<Config>) {
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;