use gdbg::dbg;
use poem::{handler, listener::TcpListener, web::Json, Request, Route, Server};
use querystring::querify;
use serde::Serialize;
use std::collections::BTreeMap;
#[derive(clap::Parser)]
pub struct Options {
#[clap(long, env = "HOST", default_value = "127.0.0.1")]
host: String,
#[clap(short = 'p', long, env = "PORT", default_value = "8080")]
port: String,
}
impl Options {
fn host(&self) -> String {
self.host.clone()
}
fn port(&self) -> String {
self.port.clone()
}
fn hostport(&self) -> String {
format!("{}:{}", self.host(), self.port())
}
fn url(&self) -> String {
format!("http://{}", self.hostport())
}
fn addr(&self) -> std::net::SocketAddr {
self.hostport().parse().unwrap()
}
pub async fn run(&mut self) -> Result<(), anyhow::Error> {
let app = Route::new().at("*", echo);
dbg!(self.url());
Ok(Server::new(TcpListener::bind(self.addr()))
.name("hello")
.run(app)
.await?)
}
}
#[derive(Debug, Serialize)]
pub struct Response {
method: String,
path: String,
query: String,
headers: BTreeMap<String, Vec<String>>,
values: BTreeMap<String, Vec<String>>,
}
pub fn echo_impl(req: &Request) -> Response {
let method = req.method().to_string();
let path = req.uri().path().to_string();
let query = req.uri().query().unwrap_or("").to_string();
let headers = req
.headers()
.iter()
.map(|(name, value)| {
(
name.as_str().to_string(),
value.to_str().unwrap().to_string(),
)
})
.fold(
BTreeMap::<String, Vec<String>>::new(),
|mut acc: BTreeMap<_, _>, (left, right)| {
acc.entry(left)
.and_modify(|values| values.push(right.clone()))
.or_insert(vec![right]);
acc
},
);
dbg!(querify(&query));
let values = querify(&query)
.iter()
.map(|(name, value)| (name.to_string(), value.to_string()))
.fold(
BTreeMap::<String, Vec<String>>::new(),
|mut acc: BTreeMap<_, _>, (left, right)| {
dbg!((&left, &right));
acc.entry(left)
.and_modify(|values| values.push(right.clone()))
.or_insert(vec![right]);
acc
},
);
Response {
method,
path,
query,
headers,
values,
}
}
#[handler]
pub fn echo(req: &Request) -> Json<Response> {
Json(echo_impl(req))
}