Update HTTP client methods to use request_with_options for improved flexibility. Adjusted related test cases and examples accordingly.

This commit is contained in:
geoffsee
2025-08-28 15:01:02 -04:00
parent 37fa59a88a
commit b96141857e
5 changed files with 36 additions and 42 deletions

2
Cargo.lock generated
View File

@@ -489,7 +489,7 @@ dependencies = [
[[package]]
name = "hyper-custom-cert"
version = "0.3.5"
version = "0.3.6"
dependencies = [
"bytes",
"http-body-util",

View File

@@ -139,7 +139,7 @@ async fn api_overview() -> Json<Value> {
/// Test default HttpClient creation
async fn test_default_client() -> Json<TestResponse> {
let client = HttpClient::new();
let result = client.request("https://httpbin.org/get").await;
let result = client.request_with_options("https://httpbin.org/get", None).await;
Json(TestResponse {
endpoint: "/test/client/default".to_string(),
@@ -156,7 +156,7 @@ async fn test_default_client() -> Json<TestResponse> {
/// Test HttpClient builder pattern
async fn test_builder_client() -> Json<TestResponse> {
let client = HttpClient::builder().build();
let result = client.request("https://httpbin.org/get").await;
let result = client.request_with_options("https://httpbin.org/get", None).await;
Json(TestResponse {
endpoint: "/test/client/builder".to_string(),
@@ -176,7 +176,7 @@ async fn test_timeout_client(Query(params): Query<TimeoutQuery>) -> Json<TestRes
let client = HttpClient::builder()
.with_timeout(Duration::from_secs(timeout_secs))
.build();
let result = client.request("https://httpbin.org/get").await;
let result = client.request_with_options("https://httpbin.org/get", None).await;
Json(TestResponse {
endpoint: "/test/client/timeout".to_string(),
@@ -204,7 +204,7 @@ async fn test_headers_client() -> Json<TestResponse> {
headers.insert("Accept".to_string(), "application/json".to_string());
let client = HttpClient::builder().with_default_headers(headers).build();
let result = client.request("https://httpbin.org/get").await;
let result = client.request_with_options("https://httpbin.org/get", None).await;
Json(TestResponse {
endpoint: "/test/client/headers".to_string(),
@@ -231,7 +231,7 @@ async fn test_combined_config() -> Json<TestResponse> {
.with_timeout(Duration::from_secs(30))
.with_default_headers(headers)
.build();
let result = client.request("https://httpbin.org/get").await;
let result = client.request_with_options("https://httpbin.org/get", None).await;
Json(TestResponse {
endpoint: "/test/client/combined".to_string(),
@@ -365,7 +365,7 @@ async fn test_insecure_feature() -> Json<TestResponse> {
/// Test HTTP GET method
async fn test_get_method() -> Json<TestResponse> {
let client = HttpClient::new();
let result = client.request("https://httpbin.org/get").await;
let result = client.request_with_options("https://httpbin.org/get", None).await;
Json(TestResponse {
endpoint: "/test/methods/get".to_string(),
@@ -383,7 +383,7 @@ async fn test_get_method() -> Json<TestResponse> {
async fn test_post_method(Json(payload): Json<PostData>) -> Json<TestResponse> {
let client = HttpClient::new();
let body = serde_json::to_vec(&payload).unwrap_or_default();
let result = client.post("https://httpbin.org/post", &body).await;
let result = client.post_with_options("https://httpbin.org/post", &body, None).await;
Json(TestResponse {
endpoint: "/test/methods/post".to_string(),
@@ -404,7 +404,7 @@ async fn test_post_method(Json(payload): Json<PostData>) -> Json<TestResponse> {
async fn test_put_method(Json(payload): Json<PostData>) -> Json<TestResponse> {
let client = HttpClient::new();
let body = serde_json::to_vec(&payload).unwrap_or_default();
let result = client.post("https://httpbin.org/put", &body).await;
let result = client.post_with_options("https://httpbin.org/put", &body, None).await;
Json(TestResponse {
endpoint: "/test/methods/put".to_string(),
@@ -424,7 +424,7 @@ async fn test_put_method(Json(payload): Json<PostData>) -> Json<TestResponse> {
/// Test HTTP DELETE method (simulated via GET since library doesn't have DELETE yet)
async fn test_delete_method() -> Json<TestResponse> {
let client = HttpClient::new();
let result = client.request("https://httpbin.org/delete").await;
let result = client.request_with_options("https://httpbin.org/delete", None).await;
Json(TestResponse {
endpoint: "/test/methods/delete".to_string(),
@@ -452,7 +452,7 @@ async fn test_custom_ca() -> Json<TestResponse> {
.with_timeout(Duration::from_secs(10))
.with_root_ca_pem(ca_pem)
.build();
let result = client.request("https://httpbin.org/get");
let result = client.request_with_options("https://httpbin.org/get", None);
let awaited = result.await;
@@ -494,7 +494,7 @@ async fn test_cert_pinning() -> Json<TestResponse> {
.with_timeout(Duration::from_secs(10))
.with_pinned_cert_sha256(pins)
.build();
let result = client.request("https://httpbin.org/get");
let result = client.request_with_options("https://httpbin.org/get", None);
let awaited = result.await;
@@ -526,7 +526,7 @@ async fn test_self_signed() -> Json<TestResponse> {
#[cfg(feature = "insecure-dangerous")]
{
let client = HttpClient::with_self_signed_certs();
let result = client.request("https://self-signed.badssl.com/");
let result = client.request_with_options("https://self-signed.badssl.com/", None);
let awaited = result.await;
@@ -562,7 +562,7 @@ async fn test_self_signed() -> Json<TestResponse> {
async fn test_custom_timeout(Path(seconds): Path<u64>) -> Json<TestResponse> {
let timeout_duration = Duration::from_secs(seconds);
let client = HttpClient::builder().with_timeout(timeout_duration).build();
let result = client.request("https://httpbin.org/delay/1");
let result = client.request_with_options("https://httpbin.org/delay/1", None);
Json(TestResponse {
endpoint: format!("/test/config/timeout/{}", seconds),
@@ -595,7 +595,7 @@ async fn test_custom_headers(Path(header_count): Path<usize>) -> Json<TestRespon
.with_timeout(Duration::from_secs(10))
.with_default_headers(headers)
.build();
let result = client.request("https://httpbin.org/headers");
let result = client.request_with_options("https://httpbin.org/headers", None);
Json(TestResponse {
endpoint: format!("/test/config/headers/{}", header_count),
@@ -622,7 +622,7 @@ async fn test_timeout_error() -> Json<TestResponse> {
let client = HttpClient::builder()
.with_timeout(Duration::from_millis(1))
.build();
let result = client.request("https://httpbin.org/delay/5");
let result = client.request_with_options("https://httpbin.org/delay/5", None);
let awaited = result.await;
Json(TestResponse {
@@ -645,7 +645,7 @@ async fn test_timeout_error() -> Json<TestResponse> {
/// Test invalid URL handling
async fn test_invalid_url() -> Json<TestResponse> {
let client = HttpClient::new();
let result = client.request("invalid-url-format");
let result = client.request_with_options("invalid-url-format", None);
let awaited = result.await;
@@ -672,7 +672,7 @@ async fn test_connection_error() -> Json<TestResponse> {
.with_timeout(Duration::from_secs(5))
.build();
// Try to connect to a non-existent host
let result = client.request("https://non-existent-host-12345.example.com/");
let result = client.request_with_options("https://non-existent-host-12345.example.com/", None);
let awaited = result.await;
Json(TestResponse {
@@ -721,7 +721,7 @@ async fn status_check() -> Json<Value> {
.as_secs();
// Test basic client creation to verify library is working
let client_test = match HttpClient::new().request("https://httpbin.org/get").await {
let client_test = match HttpClient::new().request_with_options("https://httpbin.org/get", None).await {
Ok(_) => "operational",
Err(_) => "degraded",
};

View File

@@ -1,6 +1,6 @@
[package]
name = "hyper-custom-cert"
version = "0.3.5"
version = "0.3.6"
edition = "2024"
description = "A small, ergonomic HTTP client wrapper around hyper with optional support for custom Root CAs and a dev-only insecure mode for self-signed certificates."
license = "MIT OR Apache-2.0"

View File

@@ -15,7 +15,7 @@ async fn main() {
// Demonstrate a request (now returns HttpResponse with raw body data)
let _response = client
.request("https://example.com")
.request_with_options("https://example.com", None)
.await
.expect("request should succeed on native targets");
@@ -30,7 +30,7 @@ async fn main() {
.with_timeout(Duration::from_secs(10))
.with_root_ca_pem(ca_pem)
.build();
let _ = _rustls_client.request("https://private.local").await;
let _ = _rustls_client.request_with_options("https://private.local", None).await;
// Option 2: Load CA certificate from a file path
// Note: This will panic if the file doesn't exist - ensure your cert file is available
@@ -47,13 +47,13 @@ async fn main() {
{
// Shortcut:
let _dev_client = HttpClient::with_self_signed_certs();
let _ = _dev_client.request("https://localhost:8443").await;
let _ = _dev_client.request_with_options("https://localhost:8443", None).await;
// Or explicit builder method:
let _dev_client2 = HttpClient::builder()
.insecure_accept_invalid_certs(true)
.build();
let _ = _dev_client2.request("https://localhost:8443").await;
let _ = _dev_client2.request_with_options("https://localhost:8443", None).await;
}
println!("Example finished. See README for feature flags and commands.");

View File

@@ -367,11 +367,10 @@ impl HttpClient {
}
// Add any request-specific headers from options
if let Some(options) = &options {
if let Some(headers) = &options.headers {
for (key, value) in headers {
req = req.header(key, value);
}
if let Some(options) = &options
&& let Some(headers) = &options.headers {
for (key, value) in headers {
req = req.header(key, value);
}
}
@@ -379,7 +378,7 @@ impl HttpClient {
// If options contain a timeout, temporarily modify self to use it
// This is a bit of a hack since we can't modify perform_request easily
let result = if let Some(opts) = &options {
if let Some(opts) = &options {
if let Some(timeout) = opts.timeout {
// Create a copy of self with the new timeout
let client_copy = HttpClient {
@@ -401,9 +400,7 @@ impl HttpClient {
} else {
// No options, use normal client
self.perform_request(req).await
};
result
}
}
/// Performs a POST request with the given body and returns the raw response.
@@ -505,11 +502,10 @@ impl HttpClient {
}
// Add any request-specific headers from options
if let Some(options) = &options {
if let Some(headers) = &options.headers {
for (key, value) in headers {
req = req.header(key, value);
}
if let Some(options) = &options
&& let Some(headers) = &options.headers {
for (key, value) in headers {
req = req.header(key, value);
}
}
@@ -518,7 +514,7 @@ impl HttpClient {
// If options contain a timeout, temporarily modify self to use it
// This is a bit of a hack since we can't modify perform_request easily
let result = if let Some(opts) = &options {
if let Some(opts) = &options {
if let Some(timeout) = opts.timeout {
// Create a copy of self with the new timeout
let client_copy = HttpClient {
@@ -540,9 +536,7 @@ impl HttpClient {
} else {
// No options, use normal client
self.perform_request(req).await
};
result
}
}
/// Helper method to perform HTTP requests using the configured settings.