Compare commits

...

2 commits

5 changed files with 130 additions and 10 deletions

75
Cargo.lock generated
View file

@ -26,6 +26,21 @@ dependencies = [
"memchr",
]
[[package]]
name = "android-tzdata"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
[[package]]
name = "android_system_properties"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
dependencies = [
"libc",
]
[[package]]
name = "anstream"
version = "0.6.15"
@ -147,6 +162,20 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
version = "0.4.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"
dependencies = [
"android-tzdata",
"iana-time-zone",
"js-sys",
"num-traits",
"wasm-bindgen",
"windows-targets 0.52.6",
]
[[package]]
name = "clap"
version = "4.5.20"
@ -489,6 +518,29 @@ dependencies = [
"tracing",
]
[[package]]
name = "iana-time-zone"
version = "0.1.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220"
dependencies = [
"android_system_properties",
"core-foundation-sys",
"iana-time-zone-haiku",
"js-sys",
"wasm-bindgen",
"windows-core",
]
[[package]]
name = "iana-time-zone-haiku"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
dependencies = [
"cc",
]
[[package]]
name = "idna"
version = "0.4.0"
@ -550,9 +602,9 @@ checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
[[package]]
name = "js-sys"
version = "0.3.64"
version = "0.3.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a"
checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9"
dependencies = [
"wasm-bindgen",
]
@ -642,6 +694,15 @@ dependencies = [
"tempfile",
]
[[package]]
name = "num-traits"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
]
[[package]]
name = "object"
version = "0.36.5"
@ -752,6 +813,7 @@ checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
name = "postwoman"
version = "0.2.0"
dependencies = [
"chrono",
"clap",
"http",
"indexmap",
@ -1455,6 +1517,15 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "windows-core"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "windows-registry"
version = "0.2.0"

View file

@ -6,6 +6,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
chrono = "0.4"
clap = { version = "4.5", features = ["derive"] }
http = "1.1.0"
indexmap = { version = "2.6", features = ["serde"] }

View file

@ -4,6 +4,10 @@ user_agent = "postwoman@sample/0.2.0"
[route.healthcheck]
url = "https://api.alemi.dev/"
[route.benchmark]
url = "https://api.alemi.dev/look/into/the/void"
extract = { type = "discard" }
[route.debug]
url = "https://api.alemi.dev/debug"
method = "PUT"

View file

@ -1,5 +1,7 @@
mod model;
use std::sync::Arc;
use clap::{Parser, Subcommand};
use model::{PostWomanConfig, PostWomanError};
@ -24,6 +26,14 @@ pub enum PostWomanActions {
Run {
/// regex query filter, run all with '.*'
query: String,
/// run requests in parallel
#[arg(long, default_value_t = false)]
parallel: bool,
/// repeat request N times
#[arg(long, default_value_t = 1)]
repeat: u32,
},
// Save {
@ -40,6 +50,16 @@ pub enum PostWomanActions {
// }
}
const TIMESTAMP_FMT: &str = "%H:%M:%S%.6f";
fn print_results(res: String, name: String, before: chrono::DateTime<chrono::Utc>) {
let after = chrono::Utc::now();
let elapsed = (after - before).num_milliseconds();
let timestamp = after.format(TIMESTAMP_FMT);
eprintln!(" + [{timestamp}] {name} done in {elapsed}ms", );
print!("{}", res);
}
#[tokio::main]
async fn main() -> Result<(), PostWomanError> {
let args = PostWomanArgs::parse();
@ -48,16 +68,38 @@ async fn main() -> Result<(), PostWomanError> {
let config: PostWomanConfig = toml::from_str(&collection)?;
match args.action {
PostWomanActions::Run { query } => {
PostWomanActions::Run { query, parallel, repeat } => {
let pattern = regex::Regex::new(&query)?;
let mut joinset = tokio::task::JoinSet::new();
let client = Arc::new(config.client);
for (name, endpoint) in config.route {
if pattern.find(&name).is_some() {
eprintln!("> executing {name}");
let res = endpoint
.fill()
.execute(&config.client)
.await?;
println!("{res}");
for i in 0..repeat {
let _client = client.clone();
let _endpoint = endpoint.clone();
let _name = name.clone();
let task = async move {
let before = chrono::Utc::now();
eprintln!(" : [{}] sending {_name} #{}...", before.format(TIMESTAMP_FMT), i+1);
let res = _endpoint
.fill()
.execute(&_client)
.await;
(res, _name, before)
};
if parallel {
joinset.spawn(task);
} else {
let (res, name, before) = task.await;
print_results(res?, name, before);
}
}
}
}
while let Some(j) = joinset.join_next().await {
match j {
Ok((res, name, before)) => print_results(res?, name, before),
Err(e) => eprintln!("! error joining task: {e}"),
}
}
},

View file

@ -150,7 +150,8 @@ impl Endpoint {
Ok(match self.extract.unwrap_or_default() {
StringOr::Str(_query) => todo!(),
StringOr::T(Extractor::Debug) => format!("{res:#?}"),
StringOr::T(Extractor::Discard) => "".to_string(),
StringOr::T(Extractor::Debug) => format!("{res:#?}\n"),
StringOr::T(Extractor::Body) => res.text().await?,
StringOr::T(Extractor::Header { key }) => res
.headers()
@ -181,6 +182,7 @@ pub enum Extractor {
#[default]
Debug,
Body,
Discard,
// JQL { query: String },
// Regex { pattern: String },
Header { key: String },