From 0706bfc420cf9d48a54fd174ba18996d73b05912 Mon Sep 17 00:00:00 2001 From: alemi Date: Sun, 9 Oct 2022 01:46:57 +0200 Subject: [PATCH] feat: mini http server built on hyper which throws back json --- .editorconfig | 10 ++++++++ .gitignore | 1 + .rustfmt.toml | 1 + Cargo.toml | 14 +++++++++++ src/main.rs | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 92 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitignore create mode 100644 .rustfmt.toml create mode 100644 Cargo.toml create mode 100644 src/main.rs diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..011b707 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,10 @@ +# Default to Unix-style newlines with a newline ending every file +[*] +end_of_line = lf +insert_final_newline = true +charset = utf-8 +indent_style = tab +indent_size = 4 + +[*.rs] +indent_size = 2 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/.rustfmt.toml b/.rustfmt.toml new file mode 100644 index 0000000..0cdd601 --- /dev/null +++ b/.rustfmt.toml @@ -0,0 +1 @@ +use_tabs = true diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..0bf2447 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "http-debugger" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[dependencies] +bytes = "1" +http-types = "2" +hyper = { version = "0.14", features = ["full"] } +tokio = { version = "1", features = ["full"] } +pretty_env_logger = "0.4" +serde = "1" +serde_json = "1" diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..cd76bfd --- /dev/null +++ b/src/main.rs @@ -0,0 +1,66 @@ +use std::collections::HashMap; +use std::net::SocketAddr; + +use hyper::http::HeaderValue; +use hyper::server::conn::Http; +use hyper::service::service_fn; +use hyper::{Request, Response, Body}; +use tokio::net::TcpListener; + +use serde::Serialize; + +fn str_or_repr(v: &HeaderValue) -> String { + match v.to_str() { + Ok(str) => { + str.to_string() + }, + Err(e) => { + format!("{:?} ({})", v, e) + }, + } +} + +#[derive(Serialize)] +struct InspectRequest { + pub host: String, + pub method: String, + pub headers: HashMap, + pub body: Option, + pub version: String, +} + +async fn hello(req: Request) -> Result, serde_json::error::Error> { + let response = InspectRequest { + host: req.uri().to_string(), + method: req.method().to_string(), + version: format!("{:?}", req.version()), + headers: req.headers().iter().map(|x| (x.0.to_string(), str_or_repr(x.1))).collect(), + body: Some(format!("{:?}", req.body())), + }; + + println!(" * {}", serde_json::to_string_pretty(&response)?); + + Ok(Response::new(serde_json::to_string(&response)?.into())) +} + +#[tokio::main] +pub async fn main() -> Result<(), Box> { + pretty_env_logger::init(); + + let addr: SocketAddr = ([127, 0, 0, 1], 3000).into(); + + let listener = TcpListener::bind(addr).await?; + println!("Listening on http://{}", addr); + loop { + let (stream, _) = listener.accept().await?; + + tokio::task::spawn(async move { + if let Err(err) = Http::new() + .serve_connection(stream, service_fn(hello)) + .await + { + println!("Error serving connection: {:?}", err); + } + }); + } +}