This is an automated email from the ASF dual-hosted git repository.

xuanwo pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/opendal-reqsign.git


The following commit(s) were added to refs/heads/main by this push:
     new 125362c  feat: Return credential_invalid while no credential found 
(#655)
125362c is described below

commit 125362c6ef4e116ed70c6e76260de3b47980985f
Author: Xuanwo <[email protected]>
AuthorDate: Mon Oct 13 22:50:54 2025 +0900

    feat: Return credential_invalid while no credential found (#655)
    
    `Signer` should check and return error instead of passing down to
    `RequestSigner`.
    
    ---------
    
    Signed-off-by: Xuanwo <[email protected]>
---
 core/src/signer.rs                           | 10 ++++++++--
 services/aws-v4/src/sign_request.rs          |  6 +++---
 services/azure-storage/src/sign_request.rs   |  4 +---
 services/google/src/sign_request.rs          |  5 +++--
 services/huaweicloud-obs/src/sign_request.rs | 14 ++++++++------
 5 files changed, 23 insertions(+), 16 deletions(-)

diff --git a/core/src/signer.rs b/core/src/signer.rs
index c178659..6ba2508 100644
--- a/core/src/signer.rs
+++ b/core/src/signer.rs
@@ -15,7 +15,8 @@
 // specific language governing permissions and limitations
 // under the License.
 
-use crate::{Context, ProvideCredential, Result, SignRequest, 
SigningCredential};
+use crate::{Context, Error, ProvideCredential, Result, SignRequest, 
SigningCredential};
+use std::any::type_name;
 use std::sync::{Arc, Mutex};
 use std::time::Duration;
 
@@ -81,8 +82,13 @@ impl<K: SigningCredential> Signer<K> {
             ctx
         };
 
+        let credential_ref = credential.as_ref().ok_or_else(|| {
+            Error::credential_invalid("failed to load signing credential")
+                .with_context(format!("credential_type: {}", type_name::<K>()))
+        })?;
+
         self.builder
-            .sign_request(&self.ctx, req, credential.as_ref(), expires_in)
+            .sign_request(&self.ctx, req, Some(credential_ref), expires_in)
             .await
     }
 }
diff --git a/services/aws-v4/src/sign_request.rs 
b/services/aws-v4/src/sign_request.rs
index 10c583f..49144ad 100644
--- a/services/aws-v4/src/sign_request.rs
+++ b/services/aws-v4/src/sign_request.rs
@@ -77,13 +77,13 @@ impl SignRequest for RequestSigner {
         credential: Option<&Self::Credential>,
         expires_in: Option<Duration>,
     ) -> Result<()> {
-        let now = self.time.unwrap_or_else(Timestamp::now);
-        let mut signed_req = SigningRequest::build(req)?;
-
         let Some(cred) = credential else {
             return Ok(());
         };
 
+        let now = self.time.unwrap_or_else(Timestamp::now);
+        let mut signed_req = SigningRequest::build(req)?;
+
         // canonicalize context
         canonicalize_header(&mut signed_req, cred, expires_in, now)?;
         canonicalize_query(
diff --git a/services/azure-storage/src/sign_request.rs 
b/services/azure-storage/src/sign_request.rs
index 98563f0..47384a4 100644
--- a/services/azure-storage/src/sign_request.rs
+++ b/services/azure-storage/src/sign_request.rs
@@ -73,9 +73,7 @@ impl SignRequest for RequestSigner {
         expires_in: Option<Duration>,
     ) -> Result<()> {
         let Some(cred) = credential else {
-            return Err(reqsign_core::Error::request_invalid(
-                "credential is required",
-            ));
+            return Ok(());
         };
 
         let method = if let Some(expires_in) = expires_in {
diff --git a/services/google/src/sign_request.rs 
b/services/google/src/sign_request.rs
index 4577133..34087f9 100644
--- a/services/google/src/sign_request.rs
+++ b/services/google/src/sign_request.rs
@@ -262,8 +262,9 @@ impl SignRequest for RequestSigner {
         credential: Option<&Self::Credential>,
         expires_in: Option<Duration>,
     ) -> Result<()> {
-        let cred = credential
-            .ok_or_else(|| reqsign_core::Error::credential_invalid("missing 
credential"))?;
+        let Some(cred) = credential else {
+            return Ok(());
+        };
 
         let signing_req = match expires_in {
             // Query signing - must use ServiceAccount
diff --git a/services/huaweicloud-obs/src/sign_request.rs 
b/services/huaweicloud-obs/src/sign_request.rs
index 3725511..7aaa3e2 100644
--- a/services/huaweicloud-obs/src/sign_request.rs
+++ b/services/huaweicloud-obs/src/sign_request.rs
@@ -77,8 +77,9 @@ impl SignRequest for RequestSigner {
         credential: Option<&Self::Credential>,
         expires_in: Option<Duration>,
     ) -> Result<()> {
-        let k = credential
-            .ok_or_else(|| reqsign_core::Error::credential_invalid("missing 
credential"))?;
+        let Some(cred) = credential else {
+            return Ok(());
+        };
         let now = self.time.unwrap_or_else(Timestamp::now);
 
         let method = if let Some(expires_in) = expires_in {
@@ -89,15 +90,16 @@ impl SignRequest for RequestSigner {
 
         let mut ctx = SigningRequest::build(parts)?;
 
-        let string_to_sign = string_to_sign(&mut ctx, k, now, method, 
&self.bucket)?;
-        let signature = base64_hmac_sha1(k.secret_access_key.as_bytes(), 
string_to_sign.as_bytes());
+        let string_to_sign = string_to_sign(&mut ctx, cred, now, method, 
&self.bucket)?;
+        let signature =
+            base64_hmac_sha1(cred.secret_access_key.as_bytes(), 
string_to_sign.as_bytes());
 
         match method {
             SigningMethod::Header => {
                 ctx.headers.insert(DATE, now.format_http_date().parse()?);
                 ctx.headers.insert(AUTHORIZATION, {
                     let mut value: HeaderValue =
-                        format!("OBS {}:{}", k.access_key_id, 
signature).parse()?;
+                        format!("OBS {}:{}", cred.access_key_id, 
signature).parse()?;
                     value.set_sensitive(true);
 
                     value
@@ -105,7 +107,7 @@ impl SignRequest for RequestSigner {
             }
             SigningMethod::Query(expire) => {
                 ctx.headers.insert(DATE, now.format_http_date().parse()?);
-                ctx.query_push("AccessKeyId", &k.access_key_id);
+                ctx.query_push("AccessKeyId", &cred.access_key_id);
                 ctx.query_push("Expires", (now + 
expire).as_second().to_string());
                 ctx.query_push(
                     "Signature",

Reply via email to