Skip to content

Instantly share code, notes, and snippets.

@metatoaster
Created March 19, 2025 05:03
Show Gist options
  • Save metatoaster/c8f416c03fd7390055c1f854ad38f95b to your computer and use it in GitHub Desktop.
Save metatoaster/c8f416c03fd7390055c1f854ad38f95b to your computer and use it in GitHub Desktop.
use anyhow; // 1.0.95
use reqwest::ClientBuilder; // 0.12.12
use std::{collections::BTreeMap, time::Duration, env};
use tokio::{
self,
io::{self, AsyncWriteExt}
}; // 1.43.0
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let mut args = env::args();
args.next();
if let Some(target) = args.next() {
let count = args
.next()
.map(|s| s.parse::<u32>().ok())
.flatten()
.unwrap_or(1000);
let (ok, err, timeout, sizes) = run(&target, count).await;
println!("ok = {ok}");
println!("err = {err}");
println!("timeout = {timeout}");
println!("sizes = {sizes:?}");
} else {
eprintln!("URL required.");
}
Ok(())
}
async fn run(
target: &str,
count: u32,
) -> (u32, u32, u32, BTreeMap<usize, u32>) {
let mut stdout = io::stdout();
let mut ok = 0;
let mut err = 0;
let mut timeout = 0;
let mut sizes = BTreeMap::new();
let client = ClientBuilder::new()
.connect_timeout(Duration::from_secs(1))
.timeout(Duration::from_secs(1))
.build()
.unwrap();
for i in 0..count {
let _ = stdout.write_all(format!("{i}\r").as_bytes()).await;
let _ = stdout.flush().await;
match client.get(target).send().await {
Ok(result) => {
ok += 1;
if let Ok(bytes) = result.bytes().await {
sizes.entry(bytes.len())
.and_modify(|curr| *curr += 1)
.or_insert(1);
} else {
sizes.entry(0)
.and_modify(|curr| *curr += 1)
.or_insert(1);
}
}
Err(e) => {
if e.is_timeout() {
timeout += 1;
} else {
err += 1;
}
}
}
}
(ok, err, timeout, sizes)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment