fix(io-core,signer): replace unwrap() with proper error handling (#3150)

* fix(io-core,signer): replace unwrap() with proper error handling

## io-core (issue #653 item 1)
- pool.rs: replace 8 .lock().unwrap() with poisoned recovery
- pool.rs: replace semaphore acquire unwrap with graceful fallback
- deadlock_detector.rs: replace 5 .lock().unwrap() with match/ok

## signer (issue #653 item 1)
- Add SignV2Error enum, try_pre_sign_v2, try_sign_v2
- Replace 14 unwrap() in v2 signing with ? propagation
- Add try_streaming_sign_v4, replace 5 expect("err") with descriptive errors
- get_host_addr returns Result instead of panicking

All backward-compat wrappers preserved. 95 io-core + 18 signer tests pass.

* fix: address signer and pool review comments

* test: update signer v2 string-to-sign test

* fix: address signer and pool review followups

* fix: tighten signer host and pool fallback
This commit is contained in:
安正超
2026-06-01 07:40:20 +08:00
committed by GitHub
parent 9ce9ec22d1
commit bd571a575f
6 changed files with 421 additions and 73 deletions
+34 -2
View File
@@ -46,7 +46,15 @@ pub fn try_get_host_addr(req: &request::Request<Body>) -> Result<String, HostAdd
}
pub fn get_host_addr(req: &request::Request<Body>) -> String {
try_get_host_addr(req).unwrap()
match try_get_host_addr(req) {
Ok(host) => host,
Err(HostAddrError::MissingUriHost) => match req.headers().get("host").map(|host| host.to_str()) {
Some(Ok(host)) => host.to_string(),
Some(Err(_)) => panic!("failed to resolve request host: invalid UTF-8 header value for `host`"),
None => panic!("failed to resolve request host: request uri has no host"),
},
Err(err) => panic!("failed to resolve request host: {err}"),
}
}
pub fn sign_v4_trim_all(input: &str) -> String {
@@ -63,7 +71,7 @@ where
#[cfg(test)]
mod tests {
use super::{HostAddrError, try_get_host_addr};
use super::{HostAddrError, get_host_addr, try_get_host_addr};
use http::HeaderValue;
use http::request;
use s3s::Body;
@@ -83,6 +91,30 @@ mod tests {
assert_eq!(host, "proxy.internal:9443");
}
#[test]
fn get_host_addr_preserves_legacy_string_api() {
let req = request::Request::builder()
.method(http::Method::GET)
.uri("https://bucket.example.com:9443/object")
.body(Body::empty())
.expect("request should build");
assert_eq!(get_host_addr(&req), "bucket.example.com:9443");
}
#[test]
fn get_host_addr_uses_host_header_for_relative_uri() {
let mut req = request::Request::builder()
.method(http::Method::GET)
.uri("/object")
.body(Body::empty())
.expect("request should build");
req.headers_mut()
.insert("host", HeaderValue::from_static("bucket.example.com"));
assert_eq!(get_host_addr(&req), "bucket.example.com");
}
#[test]
fn try_get_host_addr_rejects_non_utf8_host_header_value() {
let mut req = request::Request::builder()