Skip to content

Instantly share code, notes, and snippets.

@linkdd
Created June 17, 2025 12:36
Show Gist options
  • Save linkdd/851f142bc9d6ceb18fb4e1480fdee336 to your computer and use it in GitHub Desktop.
Save linkdd/851f142bc9d6ceb18fb4e1480fdee336 to your computer and use it in GitHub Desktop.
Test backend to test Hurl performance when stress testing
[package]
name = "hurl-demo-stresstest-backend"
version = "0.1.0"
edition = "2024"
[dependencies]
anyhow = "1"
tokio = { version = "1", features = ["full"] }
hyper = { version = "1", features = ["full"] }
hyper-util = { version = "0.1", features = ["full"] }
http-body-util = "0.1"
use std::convert::Infallible;
use std::net::SocketAddr;
use tokio::net::TcpListener;
use hyper::{
body::{Bytes, Incoming},
service::service_fn,
Request,
Response,
};
use hyper_util::{
server::{
conn::auto::Builder,
graceful::GracefulShutdown,
},
rt::{TokioExecutor, TokioIo},
};
use http_body_util::Full;
#[tokio::main]
async fn main() {
match server().await {
Ok(_) => println!("server stopped gracefully"),
Err(err) => eprintln!("server error: {}", err),
}
}
async fn server() -> anyhow::Result<()> {
let mut sig = std::pin::pin!(shutdown_signal());
let graceful = GracefulShutdown::new();
let address = SocketAddr::from(([0, 0, 0, 0], 8080));
let listener = TcpListener::bind(address).await?;
println!("start server");
let executor = TokioExecutor::new();
let builder = Builder::new(executor);
loop {
tokio::select! {
Ok((stream, _)) = listener.accept() => {
let io = TokioIo::new(stream);
let builder = builder.clone();
tokio::spawn(async move {
let svc = service_fn(dummy_route);
if let Err(err) = builder.serve_connection(io, svc).await {
println!("failed to serve connection: {}", err);
}
});
},
_ = &mut sig => {
drop(listener);
println!("stop listening");
break;
}
}
}
tokio::select! {
_ = graceful.shutdown() => {
println!("all connections gracefully closed");
},
_ = tokio::time::sleep(std::time::Duration::from_secs(10)) => {
println!("timed out wait for all connections to close");
}
}
Ok(())
}
async fn dummy_route(_req: Request<Incoming>) -> Result<Response<Full<Bytes>>, Infallible> {
Ok(Response::new(Full::new(Bytes::from("Hello world"))))
}
async fn shutdown_signal() {
tokio::signal::ctrl_c().await
.expect("failed to install CTRL+C signal handler");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment