#![allow(
clippy::unwrap_used,
clippy::expect_used,
unused_results,
clippy::significant_drop_tightening
)]
mod common;
use http_body_util::Full;
use hyper::body::Bytes;
use hyper::Response;
use common::TestServer;
#[tokio::test]
async fn multi_fail_on_error_mixed() {
let server = TestServer::start(|req| match req.uri().path() {
"/ok" => Response::new(Full::new(Bytes::from("ok"))),
"/err" => Response::builder().status(500).body(Full::new(Bytes::from("error"))).unwrap(),
_ => Response::new(Full::new(Bytes::from("default"))),
})
.await;
let mut multi = liburlx::Multi::new();
let mut ok_handle = liburlx::Easy::new();
ok_handle.url(&server.url("/ok")).unwrap();
ok_handle.fail_on_error(true);
multi.add(ok_handle);
let mut err_handle = liburlx::Easy::new();
err_handle.url(&server.url("/err")).unwrap();
err_handle.fail_on_error(true);
multi.add(err_handle);
let results = multi.perform().await;
assert_eq!(results.len(), 2);
assert!(results[0].is_ok());
assert_eq!(results[0].as_ref().unwrap().status(), 200);
assert!(results[1].is_err());
}
#[tokio::test]
async fn multi_with_timeouts() {
let server = TestServer::start(|_req| Response::new(Full::new(Bytes::from("ok")))).await;
let mut multi = liburlx::Multi::new();
for _ in 0..3 {
let mut easy = liburlx::Easy::new();
easy.url(&server.url("/")).unwrap();
easy.timeout(std::time::Duration::from_secs(10));
multi.add(easy);
}
let results = multi.perform().await;
assert_eq!(results.len(), 3);
assert!(results.iter().all(Result::is_ok));
}
#[tokio::test]
async fn multi_reuse_after_perform() {
let server = TestServer::start(|_req| Response::new(Full::new(Bytes::from("ok")))).await;
let mut multi = liburlx::Multi::new();
let mut easy1 = liburlx::Easy::new();
easy1.url(&server.url("/a")).unwrap();
multi.add(easy1);
let results1 = multi.perform().await;
assert_eq!(results1.len(), 1);
assert!(multi.is_empty());
let mut easy2 = liburlx::Easy::new();
easy2.url(&server.url("/b")).unwrap();
multi.add(easy2);
let results2 = multi.perform().await;
assert_eq!(results2.len(), 1);
}
#[tokio::test]
async fn multi_mixed_methods_and_bodies() {
let server = TestServer::start(|req| {
let method = req.method().to_string();
let path = req.uri().path().to_string();
Response::new(Full::new(Bytes::from(format!("{method} {path}"))))
})
.await;
let mut multi = liburlx::Multi::new();
let mut get = liburlx::Easy::new();
get.url(&server.url("/get")).unwrap();
multi.add(get);
let mut post = liburlx::Easy::new();
post.url(&server.url("/post")).unwrap();
post.method("POST");
post.body(b"data");
multi.add(post);
let mut delete = liburlx::Easy::new();
delete.url(&server.url("/delete")).unwrap();
delete.method("DELETE");
multi.add(delete);
let results = multi.perform().await;
assert_eq!(results.len(), 3);
assert_eq!(results[0].as_ref().unwrap().body_str().unwrap(), "GET /get");
assert_eq!(results[1].as_ref().unwrap().body_str().unwrap(), "POST /post");
assert_eq!(results[2].as_ref().unwrap().body_str().unwrap(), "DELETE /delete");
}
#[tokio::test]
async fn multi_with_custom_headers() {
let server = TestServer::start(|req| {
let auth = req
.headers()
.get("authorization")
.and_then(|v| v.to_str().ok())
.unwrap_or("none")
.to_string();
Response::new(Full::new(Bytes::from(auth)))
})
.await;
let mut multi = liburlx::Multi::new();
let mut with_auth = liburlx::Easy::new();
with_auth.url(&server.url("/")).unwrap();
with_auth.bearer_token("token123");
multi.add(with_auth);
let mut without_auth = liburlx::Easy::new();
without_auth.url(&server.url("/")).unwrap();
multi.add(without_auth);
let results = multi.perform().await;
assert_eq!(results.len(), 2);
assert_eq!(results[0].as_ref().unwrap().body_str().unwrap(), "Bearer token123");
assert_eq!(results[1].as_ref().unwrap().body_str().unwrap(), "none");
}
#[tokio::test]
async fn multi_with_redirects() {
let server = TestServer::start(|req| match req.uri().path() {
"/redirect" => Response::builder()
.status(302)
.header("Location", "/final")
.header("Content-Length", "0")
.body(Full::new(Bytes::new()))
.unwrap(),
"/final" => Response::new(Full::new(Bytes::from("redirected"))),
_ => Response::new(Full::new(Bytes::from("direct"))),
})
.await;
let mut multi = liburlx::Multi::new();
let mut redirect_handle = liburlx::Easy::new();
redirect_handle.url(&server.url("/redirect")).unwrap();
redirect_handle.follow_redirects(true);
multi.add(redirect_handle);
let mut direct_handle = liburlx::Easy::new();
direct_handle.url(&server.url("/direct")).unwrap();
multi.add(direct_handle);
let results = multi.perform().await;
assert_eq!(results.len(), 2);
assert_eq!(results[0].as_ref().unwrap().body_str().unwrap(), "redirected");
assert_eq!(results[1].as_ref().unwrap().body_str().unwrap(), "direct");
}