You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@opendal.apache.org by xu...@apache.org on 2026/03/24 06:49:45 UTC

(opendal) branch main updated: refactor(core): route reqsign send via accessor http client (#7234)

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.git


The following commit(s) were added to refs/heads/main by this push:
     new 0f45d6aff refactor(core): route reqsign send via accessor http client (#7234)
0f45d6aff is described below

commit 0f45d6aff459c4cddbbd8432027455801115db49
Author: Xuanwo <gi...@xuanwo.io>
AuthorDate: Tue Mar 24 14:49:38 2026 +0800

    refactor(core): route reqsign send via accessor http client (#7234)
    
    * refactor(core): route reqsign send via accessor http client
    
    * code tidy (#7235)
    
    Signed-off-by: tison <wa...@gmail.com>
    
    * refactor(core): upgrade reqsign to 3.0.0
    
    ---------
    
    Signed-off-by: tison <wa...@gmail.com>
    Co-authored-by: tison <wa...@gmail.com>
---
 core/Cargo.lock                       | 153 +++++++++++++++--------------
 core/core/Cargo.toml                  |   1 +
 core/core/src/raw/http_util/client.rs |  44 ++++++++-
 core/core/src/raw/http_util/mod.rs    |   1 +
 core/services/azblob/Cargo.toml       |   7 +-
 core/services/azblob/src/backend.rs   |  10 +-
 core/services/azdls/Cargo.toml        |   7 +-
 core/services/azdls/src/backend.rs    |  10 +-
 core/services/azfile/Cargo.toml       |   7 +-
 core/services/azfile/src/backend.rs   |  10 +-
 core/services/cos/Cargo.toml          |  10 +-
 core/services/cos/src/backend.rs      |  17 ++--
 core/services/gcs/Cargo.toml          |  11 +--
 core/services/gcs/src/backend.rs      | 177 +++-------------------------------
 core/services/ghac/Cargo.toml         |   4 +-
 core/services/obs/Cargo.toml          |   7 +-
 core/services/obs/src/backend.rs      |  10 +-
 core/services/oss/Cargo.toml          |   7 +-
 core/services/oss/src/backend.rs      |  10 +-
 core/services/s3/Cargo.toml           |  11 +--
 core/services/s3/src/backend.rs       |  21 ++--
 21 files changed, 207 insertions(+), 328 deletions(-)

diff --git a/core/Cargo.lock b/core/Cargo.lock
index 01cfa9ae8..98ea3d72d 100644
--- a/core/Cargo.lock
+++ b/core/Cargo.lock
@@ -668,6 +668,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6b5ce75405893cd713f9ab8e297d8e438f624dde7d706108285f7e17a25a180f"
 dependencies = [
  "aws-lc-sys",
+ "untrusted 0.7.1",
  "zeroize",
 ]
 
@@ -4734,6 +4735,23 @@ dependencies = [
  "simple_asn1",
 ]
 
+[[package]]
+name = "jsonwebtoken"
+version = "10.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0529410abe238729a60b108898784df8984c87f6054c9c4fcacc47e4803c1ce1"
+dependencies = [
+ "aws-lc-rs",
+ "base64 0.22.1",
+ "getrandom 0.2.16",
+ "js-sys",
+ "pem",
+ "serde",
+ "serde_json",
+ "signature 2.2.0",
+ "simple_asn1",
+]
+
 [[package]]
 name = "kv-log-macro"
 version = "1.0.7"
@@ -6028,8 +6046,9 @@ dependencies = [
  "moka",
  "percent-encoding",
  "pretty_assertions",
- "quick-xml",
+ "quick-xml 0.38.4",
  "rand 0.8.5",
+ "reqsign-core",
  "reqwest",
  "serde",
  "serde_json",
@@ -6371,11 +6390,10 @@ dependencies = [
  "opendal-core",
  "opendal-service-azure-common",
  "pretty_assertions",
- "quick-xml",
+ "quick-xml 0.38.4",
  "reqsign-azure-storage",
  "reqsign-core",
  "reqsign-file-read-tokio",
- "reqsign-http-send-reqwest",
  "serde",
  "serde_json",
  "sha2",
@@ -6392,11 +6410,10 @@ dependencies = [
  "log",
  "opendal-core",
  "opendal-service-azure-common",
- "quick-xml",
+ "quick-xml 0.38.4",
  "reqsign-azure-storage",
  "reqsign-core",
  "reqsign-file-read-tokio",
- "reqsign-http-send-reqwest",
  "serde",
  "serde_json",
  "tokio",
@@ -6411,11 +6428,10 @@ dependencies = [
  "log",
  "opendal-core",
  "opendal-service-azure-common",
- "quick-xml",
+ "quick-xml 0.38.4",
  "reqsign-azure-storage",
  "reqsign-core",
  "reqsign-file-read-tokio",
- "reqsign-http-send-reqwest",
  "serde",
  "tokio",
 ]
@@ -6483,12 +6499,10 @@ dependencies = [
  "http 1.4.0",
  "log",
  "opendal-core",
- "quick-xml",
+ "quick-xml 0.38.4",
  "reqsign-core",
  "reqsign-file-read-tokio",
- "reqsign-http-send-reqwest",
  "reqsign-tencent-cos",
- "reqwest",
  "serde",
  "tokio",
 ]
@@ -6603,12 +6617,10 @@ dependencies = [
  "log",
  "opendal-core",
  "percent-encoding",
- "quick-xml",
+ "quick-xml 0.38.4",
  "reqsign-core",
  "reqsign-file-read-tokio",
  "reqsign-google",
- "reqsign-http-send-reqwest",
- "reqwest",
  "serde",
  "serde_json",
  "tokio",
@@ -6853,10 +6865,9 @@ dependencies = [
  "http 1.4.0",
  "log",
  "opendal-core",
- "quick-xml",
+ "quick-xml 0.38.4",
  "reqsign-core",
  "reqsign-file-read-tokio",
- "reqsign-http-send-reqwest",
  "reqsign-huaweicloud-obs",
  "serde",
  "tokio",
@@ -6897,11 +6908,10 @@ dependencies = [
  "log",
  "opendal-core",
  "pretty_assertions",
- "quick-xml",
+ "quick-xml 0.38.4",
  "reqsign-aliyun-oss",
  "reqsign-core",
  "reqsign-file-read-tokio",
- "reqsign-http-send-reqwest",
  "serde",
  "tokio",
 ]
@@ -6985,15 +6995,14 @@ dependencies = [
  "md-5",
  "opendal-core",
  "pretty_assertions",
- "quick-xml",
+ "quick-xml 0.38.4",
  "reqsign-aws-v4",
  "reqsign-core",
  "reqsign-file-read-tokio",
- "reqsign-http-send-reqwest",
- "reqwest",
  "serde",
  "serde_json",
  "tokio",
+ "url",
 ]
 
 [[package]]
@@ -7069,7 +7078,7 @@ dependencies = [
  "log",
  "opendal-core",
  "percent-encoding",
- "quick-xml",
+ "quick-xml 0.38.4",
  "serde",
  "serde_json",
  "sha1",
@@ -7109,7 +7118,7 @@ dependencies = [
  "log",
  "md-5",
  "opendal-core",
- "quick-xml",
+ "quick-xml 0.38.4",
  "serde",
  "serde_json",
  "sha1",
@@ -7138,7 +7147,7 @@ dependencies = [
  "http 1.4.0",
  "log",
  "opendal-core",
- "quick-xml",
+ "quick-xml 0.38.4",
  "serde",
  "serde_json",
  "tokio",
@@ -7154,7 +7163,7 @@ dependencies = [
  "log",
  "mea 0.6.0",
  "opendal-core",
- "quick-xml",
+ "quick-xml 0.38.4",
  "serde",
  "tokio",
 ]
@@ -7183,7 +7192,7 @@ dependencies = [
  "http 1.4.0",
  "log",
  "opendal-core",
- "quick-xml",
+ "quick-xml 0.38.4",
  "serde",
  "serde_json",
  "tokio",
@@ -8255,6 +8264,16 @@ dependencies = [
  "serde",
 ]
 
+[[package]]
+name = "quick-xml"
+version = "0.39.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "958f21e8e7ceb5a1aa7fa87fab28e7c75976e0bfe7e23ff069e0a260f894067d"
+dependencies = [
+ "memchr",
+ "serde",
+]
+
 [[package]]
 name = "quick_cache"
 version = "0.5.2"
@@ -8655,35 +8674,34 @@ dependencies = [
 
 [[package]]
 name = "reqsign-aliyun-oss"
-version = "2.0.2"
+version = "3.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca53e7f1b5767da409d861e864d6c2867e710a500103582196bd6fff8f103d32"
+checksum = "57ac2757f3140aa2e213b554148ae0b52733e624fc6723f0cc6bb3d440176c95"
 dependencies = [
  "anyhow",
- "async-trait",
  "form_urlencoded",
  "http 1.4.0",
  "log",
  "percent-encoding",
  "reqsign-core",
+ "rust-ini",
  "serde",
  "serde_json",
 ]
 
 [[package]]
 name = "reqsign-aws-v4"
-version = "2.0.1"
+version = "3.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4510c2a3e42b653cf788d560a3d54b0ae4cc315a62aaba773554f18319c0db0b"
+checksum = "44eaca382e94505a49f1a4849658d153aebf79d9c1a58e5dd3b10361511e9f43"
 dependencies = [
  "anyhow",
- "async-trait",
  "bytes",
  "form_urlencoded",
  "http 1.4.0",
  "log",
  "percent-encoding",
- "quick-xml",
+ "quick-xml 0.39.2",
  "reqsign-core",
  "rust-ini",
  "serde",
@@ -8694,17 +8712,16 @@ dependencies = [
 
 [[package]]
 name = "reqsign-azure-storage"
-version = "2.0.2"
+version = "3.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "153687178cff1ba9fe13d5f43c7364a3b0cf70751b9ef44ae03d4385c7558085"
+checksum = "7a321980405d596bd34aaf95c4722a3de4128a67fd19e74a81a83aa3fdf082e6"
 dependencies = [
  "anyhow",
- "async-trait",
  "base64 0.22.1",
  "bytes",
  "form_urlencoded",
  "http 1.4.0",
- "jsonwebtoken",
+ "jsonwebtoken 10.3.0",
  "log",
  "pem",
  "percent-encoding",
@@ -8717,15 +8734,15 @@ dependencies = [
 
 [[package]]
 name = "reqsign-core"
-version = "2.0.2"
+version = "3.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ba66eb941c0f723269a394baf3b19a2fa697a1e593f3e902779df6c35d24e21"
+checksum = "b10302cf0a7d7e7352ba211fc92c3c5bebf1286153e49cc5aa87348078a8e102"
 dependencies = [
  "anyhow",
- "async-trait",
  "base64 0.22.1",
  "bytes",
  "form_urlencoded",
+ "futures",
  "hex",
  "hmac",
  "http 1.4.0",
@@ -8739,61 +8756,42 @@ dependencies = [
 
 [[package]]
 name = "reqsign-file-read-tokio"
-version = "2.0.2"
+version = "3.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "702f12a867bf8e507de907fa0f4d75b96469ace7edd33fcc1fc8a8ef58f3c8d2"
+checksum = "e2d89295b3d17abea31851cc8de55d843d89c52132c864963c38d41920613dc5"
 dependencies = [
  "anyhow",
- "async-trait",
  "reqsign-core",
  "tokio",
 ]
 
 [[package]]
 name = "reqsign-google"
-version = "2.0.2"
+version = "3.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "acee8b90b1c8bb30a9abb9a9778c7862d94459a9391396e1c2a370d6b9c1e3d5"
+checksum = "35cc609b49c69e76ecaceb775a03f792d1ed3e7755ab3548d4534fd801e3242e"
 dependencies = [
- "async-trait",
  "form_urlencoded",
  "http 1.4.0",
- "jsonwebtoken",
+ "jsonwebtoken 10.3.0",
  "log",
  "percent-encoding",
- "rand 0.8.5",
+ "reqsign-aws-v4",
  "reqsign-core",
  "rsa",
  "serde",
  "serde_json",
  "sha2",
-]
-
-[[package]]
-name = "reqsign-http-send-reqwest"
-version = "2.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "46186bce769674f9200ad01af6f2ca42de3e819ddc002fff1edae135bfb6cd9c"
-dependencies = [
- "anyhow",
- "async-trait",
- "bytes",
- "futures-channel",
- "http 1.4.0",
- "http-body-util",
- "reqsign-core",
- "reqwest",
- "wasm-bindgen-futures",
+ "tokio",
 ]
 
 [[package]]
 name = "reqsign-huaweicloud-obs"
-version = "2.0.2"
+version = "3.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ef663039ba605fb73ca2837215ed082fc264fd815395c72fa93b31c46a32081"
+checksum = "8df54ec7de5d7a5b917695a67baba53ec6fa5d75ce4c4f4550db68618779a6d7"
 dependencies = [
  "anyhow",
- "async-trait",
  "http 1.4.0",
  "log",
  "percent-encoding",
@@ -8802,12 +8800,11 @@ dependencies = [
 
 [[package]]
 name = "reqsign-tencent-cos"
-version = "2.0.2"
+version = "3.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3698e12fecf5976b9b6591c855afc0b3633c14526b935a61c885e573c2c9abd4"
+checksum = "e128f19525861dbded59e1e7c17653a8ed63d573ca04aed708d552dbef5bb32a"
 dependencies = [
  "anyhow",
- "async-trait",
  "http 1.4.0",
  "log",
  "percent-encoding",
@@ -8918,7 +8915,7 @@ dependencies = [
  "cfg-if",
  "getrandom 0.2.16",
  "libc",
- "untrusted",
+ "untrusted 0.9.0",
  "windows-sys 0.52.0",
 ]
 
@@ -9276,7 +9273,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765"
 dependencies = [
  "ring",
- "untrusted",
+ "untrusted 0.9.0",
 ]
 
 [[package]]
@@ -9288,7 +9285,7 @@ dependencies = [
  "aws-lc-rs",
  "ring",
  "rustls-pki-types",
- "untrusted",
+ "untrusted 0.9.0",
 ]
 
 [[package]]
@@ -9385,7 +9382,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414"
 dependencies = [
  "ring",
- "untrusted",
+ "untrusted 0.9.0",
 ]
 
 [[package]]
@@ -10312,7 +10309,7 @@ dependencies = [
  "hex",
  "http 1.4.0",
  "ipnet",
- "jsonwebtoken",
+ "jsonwebtoken 9.3.1",
  "lexicmp",
  "linfa-linalg",
  "md-5",
@@ -11398,6 +11395,12 @@ version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "eb066959b24b5196ae73cb057f45598450d2c5f71460e98c49b738086eff9c06"
 
+[[package]]
+name = "untrusted"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
+
 [[package]]
 name = "untrusted"
 version = "0.9.0"
diff --git a/core/core/Cargo.toml b/core/core/Cargo.toml
index a9298eeb1..56b06864b 100644
--- a/core/core/Cargo.toml
+++ b/core/core/Cargo.toml
@@ -75,6 +75,7 @@ md-5 = "0.10"
 mea = { workspace = true }
 percent-encoding = "2"
 quick-xml = { workspace = true, features = ["serialize", "overlapped-lists"] }
+reqsign-core = { version = "3.0.0", default-features = false }
 reqwest = { version = "0.12.24", features = [
   "stream",
 ], default-features = false }
diff --git a/core/core/src/raw/http_util/client.rs b/core/core/src/raw/http_util/client.rs
index 4c69cb890..5be2365f2 100644
--- a/core/core/src/raw/http_util/client.rs
+++ b/core/core/src/raw/http_util/client.rs
@@ -52,7 +52,7 @@ pub static GLOBAL_REQWEST_CLIENT: LazyLock<reqwest::Client> = LazyLock::new(reqw
 /// HttpFetcher is a type erased [`HttpFetch`].
 pub type HttpFetcher = Arc<dyn HttpFetchDyn>;
 
-/// A HTTP client instance for OpenDAL's services.
+/// An HTTP client instance for OpenDAL's services.
 ///
 /// # Notes
 ///
@@ -62,6 +62,20 @@ pub struct HttpClient {
     fetcher: HttpFetcher,
 }
 
+/// A reqsign `HttpSend` implementation that always forwards requests to the
+/// current http client stored inside [`AccessorInfo`].
+#[derive(Clone)]
+pub struct AccessorInfoHttpSend {
+    info: Arc<AccessorInfo>,
+}
+
+impl AccessorInfoHttpSend {
+    /// Create a new [`AccessorInfoHttpSend`].
+    pub fn new(info: Arc<AccessorInfo>) -> Self {
+        Self { info }
+    }
+}
+
 /// We don't want users to know details about our clients.
 impl Debug for HttpClient {
     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
@@ -69,6 +83,12 @@ impl Debug for HttpClient {
     }
 }
 
+impl Debug for AccessorInfoHttpSend {
+    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+        f.debug_struct("AccessorInfoHttpSend").finish()
+    }
+}
+
 impl Default for HttpClient {
     fn default() -> Self {
         Self {
@@ -109,6 +129,28 @@ impl HttpClient {
     }
 }
 
+impl reqsign_core::HttpSend for HttpClient {
+    async fn http_send(&self, req: Request<Bytes>) -> reqsign_core::Result<Response<Bytes>> {
+        let req = req.map(Buffer::from);
+        let resp = self.send(req).await.map_err(|err| {
+            let retryable = err.is_temporary();
+            reqsign_core::Error::unexpected("send request via OpenDAL HttpClient")
+                .with_source(err)
+                .set_retryable(retryable)
+        })?;
+
+        let (parts, body) = resp.into_parts();
+        Ok(Response::from_parts(parts, body.to_bytes()))
+    }
+}
+
+impl reqsign_core::HttpSend for AccessorInfoHttpSend {
+    async fn http_send(&self, req: Request<Bytes>) -> reqsign_core::Result<Response<Bytes>> {
+        let client = self.info.http_client();
+        reqsign_core::HttpSend::http_send(&client, req).await
+    }
+}
+
 /// HttpFetch is the trait to fetch a request in async way.
 /// User should implement this trait to provide their own http client.
 pub trait HttpFetch: Send + Sync + Unpin + 'static {
diff --git a/core/core/src/raw/http_util/mod.rs b/core/core/src/raw/http_util/mod.rs
index ae6b1e585..93ef4d167 100644
--- a/core/core/src/raw/http_util/mod.rs
+++ b/core/core/src/raw/http_util/mod.rs
@@ -23,6 +23,7 @@
 //! it easier to develop services and layers outside opendal.
 
 mod client;
+pub use client::AccessorInfoHttpSend;
 /// temporary client used by several features
 #[allow(unused_imports)]
 pub use client::GLOBAL_REQWEST_CLIENT;
diff --git a/core/services/azblob/Cargo.toml b/core/services/azblob/Cargo.toml
index a0dffe4d0..0895d34df 100644
--- a/core/services/azblob/Cargo.toml
+++ b/core/services/azblob/Cargo.toml
@@ -38,10 +38,9 @@ log = { workspace = true }
 opendal-core = { path = "../../core", version = "0.55.0", default-features = false }
 opendal-service-azure-common = { path = "../azure-common", version = "0.55.0" }
 quick-xml = { workspace = true, features = ["serialize", "overlapped-lists"] }
-reqsign-azure-storage = { version = "2.0.2", default-features = false }
-reqsign-core = { version = "2.0.1", default-features = false }
-reqsign-file-read-tokio = { version = "2.0.1", default-features = false }
-reqsign-http-send-reqwest = { version = "2.0.1", default-features = false }
+reqsign-azure-storage = { version = "3.0.0", default-features = false }
+reqsign-core = { version = "3.0.0", default-features = false }
+reqsign-file-read-tokio = { version = "3.0.0", default-features = false }
 serde = { workspace = true, features = ["derive"] }
 sha2 = { workspace = true }
 uuid = { workspace = true, features = ["v4", "serde"] }
diff --git a/core/services/azblob/src/backend.rs b/core/services/azblob/src/backend.rs
index 69def7c3a..5b9d98936 100644
--- a/core/services/azblob/src/backend.rs
+++ b/core/services/azblob/src/backend.rs
@@ -32,7 +32,6 @@ use reqsign_core::OsEnv;
 use reqsign_core::Signer;
 use reqsign_core::StaticEnv;
 use reqsign_file_read_tokio::TokioFileRead;
-use reqsign_http_send_reqwest::ReqwestHttpSend;
 use sha2::Digest;
 use sha2::Sha256;
 
@@ -369,9 +368,11 @@ impl Builder for AzblobBuilder {
             }
         };
 
+        let info = Arc::new(AccessorInfo::default());
+
         let ctx = Context::new()
             .with_file_read(TokioFileRead)
-            .with_http_send(ReqwestHttpSend::new(GLOBAL_REQWEST_CLIENT.clone()))
+            .with_http_send(AccessorInfoHttpSend::new(info.clone()))
             .with_env(StaticEnv {
                 home_dir: os_env.home_dir(),
                 envs,
@@ -401,8 +402,7 @@ impl Builder for AzblobBuilder {
         Ok(AzblobBackend {
             core: Arc::new(AzblobCore {
                 info: {
-                    let am = AccessorInfo::default();
-                    am.set_scheme(AZBLOB_SCHEME)
+                    info.set_scheme(AZBLOB_SCHEME)
                         .set_root(&root)
                         .set_name(container)
                         .set_native_capability(Capability {
@@ -447,7 +447,7 @@ impl Builder for AzblobBuilder {
                             ..Default::default()
                         });
 
-                    am.into()
+                    info.clone()
                 },
                 root,
                 endpoint,
diff --git a/core/services/azdls/Cargo.toml b/core/services/azdls/Cargo.toml
index cd7af72a2..0313c8fc9 100644
--- a/core/services/azdls/Cargo.toml
+++ b/core/services/azdls/Cargo.toml
@@ -37,10 +37,9 @@ log = { workspace = true }
 opendal-core = { path = "../../core", version = "0.55.0", default-features = false }
 opendal-service-azure-common = { path = "../azure-common", version = "0.55.0" }
 quick-xml = { workspace = true, features = ["serialize", "overlapped-lists"] }
-reqsign-azure-storage = { version = "2.0.2", default-features = false }
-reqsign-core = { version = "2.0.1", default-features = false }
-reqsign-file-read-tokio = { version = "2.0.1", default-features = false }
-reqsign-http-send-reqwest = { version = "2.0.1", default-features = false }
+reqsign-azure-storage = { version = "3.0.0", default-features = false }
+reqsign-core = { version = "3.0.0", default-features = false }
+reqsign-file-read-tokio = { version = "3.0.0", default-features = false }
 serde = { workspace = true, features = ["derive"] }
 serde_json = { workspace = true }
 
diff --git a/core/services/azdls/src/backend.rs b/core/services/azdls/src/backend.rs
index e162cd437..8409dcb04 100644
--- a/core/services/azdls/src/backend.rs
+++ b/core/services/azdls/src/backend.rs
@@ -30,7 +30,6 @@ use reqsign_core::OsEnv;
 use reqsign_core::Signer;
 use reqsign_core::StaticEnv;
 use reqsign_file_read_tokio::TokioFileRead;
-use reqsign_http_send_reqwest::ReqwestHttpSend;
 
 use super::AZDLS_SCHEME;
 use super::config::AzdlsConfig;
@@ -293,9 +292,11 @@ impl Builder for AzdlsBuilder {
         }
 
         let os_env = OsEnv;
+        let info = Arc::new(AccessorInfo::default());
+
         let ctx = Context::new()
             .with_file_read(TokioFileRead)
-            .with_http_send(ReqwestHttpSend::new(GLOBAL_REQWEST_CLIENT.clone()))
+            .with_http_send(AccessorInfoHttpSend::new(info.clone()))
             .with_env(StaticEnv {
                 home_dir: os_env.home_dir(),
                 envs,
@@ -319,8 +320,7 @@ impl Builder for AzdlsBuilder {
         Ok(AzdlsBackend {
             core: Arc::new(AzdlsCore {
                 info: {
-                    let am = AccessorInfo::default();
-                    am.set_scheme(AZDLS_SCHEME)
+                    info.set_scheme(AZDLS_SCHEME)
                         .set_root(&root)
                         .set_name(filesystem)
                         .set_native_capability(Capability {
@@ -348,7 +348,7 @@ impl Builder for AzdlsBuilder {
                             ..Default::default()
                         });
 
-                    am.into()
+                    info.clone()
                 },
                 filesystem: self.config.filesystem.clone(),
                 root,
diff --git a/core/services/azfile/Cargo.toml b/core/services/azfile/Cargo.toml
index 13e1f3be3..e34558e64 100644
--- a/core/services/azfile/Cargo.toml
+++ b/core/services/azfile/Cargo.toml
@@ -37,10 +37,9 @@ log = { workspace = true }
 opendal-core = { path = "../../core", version = "0.55.0", default-features = false }
 opendal-service-azure-common = { path = "../azure-common", version = "0.55.0" }
 quick-xml = { workspace = true, features = ["serialize", "overlapped-lists"] }
-reqsign-azure-storage = { version = "2.0.2", default-features = false }
-reqsign-core = { version = "2.0.1", default-features = false }
-reqsign-file-read-tokio = { version = "2.0.1", default-features = false }
-reqsign-http-send-reqwest = { version = "2.0.1", default-features = false }
+reqsign-azure-storage = { version = "3.0.0", default-features = false }
+reqsign-core = { version = "3.0.0", default-features = false }
+reqsign-file-read-tokio = { version = "3.0.0", default-features = false }
 serde = { workspace = true, features = ["derive"] }
 
 [dev-dependencies]
diff --git a/core/services/azfile/src/backend.rs b/core/services/azfile/src/backend.rs
index 6c8d7b492..ede0296c1 100644
--- a/core/services/azfile/src/backend.rs
+++ b/core/services/azfile/src/backend.rs
@@ -30,7 +30,6 @@ use reqsign_core::OsEnv;
 use reqsign_core::Signer;
 use reqsign_core::StaticEnv;
 use reqsign_file_read_tokio::TokioFileRead;
-use reqsign_http_send_reqwest::ReqwestHttpSend;
 
 use super::AZFILE_SCHEME;
 use super::config::AzfileConfig;
@@ -209,9 +208,11 @@ impl Builder for AzfileBuilder {
         }
 
         let os_env = OsEnv;
+        let info = Arc::new(AccessorInfo::default());
+
         let ctx = Context::new()
             .with_file_read(TokioFileRead)
-            .with_http_send(ReqwestHttpSend::new(GLOBAL_REQWEST_CLIENT.clone()))
+            .with_http_send(AccessorInfoHttpSend::new(info.clone()))
             .with_env(StaticEnv {
                 home_dir: os_env.home_dir(),
                 envs,
@@ -232,8 +233,7 @@ impl Builder for AzfileBuilder {
         Ok(AzfileBackend {
             core: Arc::new(AzfileCore {
                 info: {
-                    let am = AccessorInfo::default();
-                    am.set_scheme(AZFILE_SCHEME)
+                    info.set_scheme(AZFILE_SCHEME)
                         .set_root(&root)
                         .set_native_capability(Capability {
                             stat: true,
@@ -254,7 +254,7 @@ impl Builder for AzfileBuilder {
                             ..Default::default()
                         });
 
-                    am.into()
+                    info.clone()
                 },
                 root,
                 endpoint,
diff --git a/core/services/cos/Cargo.toml b/core/services/cos/Cargo.toml
index aae8ee078..a96fad51b 100644
--- a/core/services/cos/Cargo.toml
+++ b/core/services/cos/Cargo.toml
@@ -36,13 +36,9 @@ http = { workspace = true }
 log = { workspace = true }
 opendal-core = { path = "../../core", version = "0.55.0", default-features = false }
 quick-xml = { workspace = true, features = ["serialize", "overlapped-lists"] }
-reqsign-core = { version = "2.0.1", default-features = false }
-reqsign-file-read-tokio = { version = "2.0.1", default-features = false }
-reqsign-http-send-reqwest = { version = "2.0.1", default-features = false }
-reqsign-tencent-cos = { version = "2.0.2", default-features = false }
-reqwest = { version = "0.12.24", default-features = false, features = [
-  "stream",
-] }
+reqsign-core = { version = "3.0.0", default-features = false }
+reqsign-file-read-tokio = { version = "3.0.0", default-features = false }
+reqsign-tencent-cos = { version = "3.0.0", default-features = false }
 serde = { workspace = true, features = ["derive"] }
 
 [dev-dependencies]
diff --git a/core/services/cos/src/backend.rs b/core/services/cos/src/backend.rs
index 164c6f6a1..67ba9ad3e 100644
--- a/core/services/cos/src/backend.rs
+++ b/core/services/cos/src/backend.rs
@@ -27,7 +27,6 @@ use reqsign_core::Env as _;
 use reqsign_core::OsEnv;
 use reqsign_core::Signer;
 use reqsign_file_read_tokio::TokioFileRead;
-use reqsign_http_send_reqwest::ReqwestHttpSend;
 use reqsign_tencent_cos::DefaultCredentialProvider;
 use reqsign_tencent_cos::RequestSigner;
 use reqsign_tencent_cos::StaticCredentialProvider;
@@ -43,9 +42,6 @@ use super::lister::CosObjectVersionsLister;
 use super::writer::CosWriter;
 use super::writer::CosWriters;
 use opendal_core::raw::*;
-use std::sync::LazyLock;
-
-static GLOBAL_REQWEST_CLIENT: LazyLock<reqwest::Client> = LazyLock::new(reqwest::Client::new);
 use opendal_core::*;
 
 /// Tencent-Cloud COS services support.
@@ -181,17 +177,19 @@ impl Builder for CosBuilder {
         let endpoint = uri.host().unwrap().replace(&format!("//{bucket}."), "//");
         debug!("backend use endpoint {}", &endpoint);
 
+        let info = Arc::new(AccessorInfo::default());
+
         let os_env = OsEnv;
         let envs = os_env.vars();
         let ctx = Context::new()
             .with_file_read(TokioFileRead)
-            .with_http_send(ReqwestHttpSend::new(GLOBAL_REQWEST_CLIENT.clone()))
+            .with_http_send(AccessorInfoHttpSend::new(info.clone()))
             .with_env(os_env);
 
         let mut credential = if self.config.disable_config_load {
             DefaultCredentialProvider::builder()
-                .disable_env(true)
-                .disable_assume_role(true)
+                .no_env()
+                .no_web_identity()
                 .build()
         } else {
             DefaultCredentialProvider::new()
@@ -222,8 +220,7 @@ impl Builder for CosBuilder {
         Ok(CosBackend {
             core: Arc::new(CosCore {
                 info: {
-                    let am = AccessorInfo::default();
-                    am.set_scheme(COS_SCHEME)
+                    info.set_scheme(COS_SCHEME)
                         .set_root(&root)
                         .set_name(&bucket)
                         .set_native_capability(Capability {
@@ -282,7 +279,7 @@ impl Builder for CosBuilder {
                             ..Default::default()
                         });
 
-                    am.into()
+                    info.clone()
                 },
                 bucket: bucket.clone(),
                 root,
diff --git a/core/services/gcs/Cargo.toml b/core/services/gcs/Cargo.toml
index 46c76e51e..2376a0427 100644
--- a/core/services/gcs/Cargo.toml
+++ b/core/services/gcs/Cargo.toml
@@ -38,14 +38,9 @@ log = { workspace = true }
 opendal-core = { path = "../../core", version = "0.55.0", default-features = false }
 percent-encoding = "2.3"
 quick-xml = { workspace = true, features = ["serialize"] }
-reqsign-core = { version = "2.0.1", default-features = false }
-reqsign-file-read-tokio = { version = "2.0.1", default-features = false }
-reqsign-google = { version = "2.0.2", default-features = false }
-reqsign-http-send-reqwest = { version = "2.0.1", default-features = false }
-reqwest = { version = "0.12.24", default-features = false, features = [
-  "json",
-  "stream",
-] }
+reqsign-core = { version = "3.0.0", default-features = false }
+reqsign-file-read-tokio = { version = "3.0.0", default-features = false }
+reqsign-google = { version = "3.0.0", default-features = false }
 serde = { workspace = true, features = ["derive"] }
 serde_json = { workspace = true }
 tokio = { workspace = true, features = ["rt"] }
diff --git a/core/services/gcs/src/backend.rs b/core/services/gcs/src/backend.rs
index 36d2ebbb6..7890e1f31 100644
--- a/core/services/gcs/src/backend.rs
+++ b/core/services/gcs/src/backend.rs
@@ -17,10 +17,7 @@
 
 use std::fmt::Debug;
 use std::sync::Arc;
-use std::sync::LazyLock;
-use std::time::Duration;
 
-use bytes::Bytes;
 use http::Response;
 use http::StatusCode;
 use log::debug;
@@ -31,15 +28,14 @@ use reqsign_core::ProvideCredential;
 use reqsign_core::ProvideCredentialChain;
 use reqsign_core::Signer;
 use reqsign_core::StaticEnv;
-use reqsign_core::time::Timestamp;
 use reqsign_file_read_tokio::TokioFileRead;
 use reqsign_google::Credential;
 use reqsign_google::DefaultCredentialProvider;
+use reqsign_google::FileCredentialProvider;
 use reqsign_google::RequestSigner;
 use reqsign_google::StaticCredentialProvider;
-use reqsign_google::Token;
-use reqsign_http_send_reqwest::ReqwestHttpSend;
-use serde::Deserialize;
+use reqsign_google::TokenCredentialProvider;
+use reqsign_google::VmMetadataCredentialProvider;
 
 use super::GCS_SCHEME;
 use super::config::GcsConfig;
@@ -52,8 +48,6 @@ use super::writer::GcsWriters;
 use opendal_core::raw::*;
 use opendal_core::*;
 
-static GLOBAL_REQWEST_CLIENT: LazyLock<reqwest::Client> = LazyLock::new(reqwest::Client::new);
-
 const DEFAULT_GCS_ENDPOINT: &str = "https://storage.googleapis.com";
 const DEFAULT_GCS_SCOPE: &str = "https://www.googleapis.com/auth/devstorage.read_write";
 
@@ -65,143 +59,6 @@ pub struct GcsBuilder {
     pub(super) credential_provider_chain: Option<ProvideCredentialChain<Credential>>,
 }
 
-// TODO(remove): drop this adapter once reqsign-google provides a built-in
-// static access token provider.
-// Tracking issue: https://github.com/apache/opendal-reqsign/issues/694
-#[derive(Clone, Debug)]
-struct StaticTokenCredentialProvider {
-    token: String,
-}
-
-impl StaticTokenCredentialProvider {
-    fn new(token: impl Into<String>) -> Self {
-        Self {
-            token: token.into(),
-        }
-    }
-}
-
-#[async_trait::async_trait]
-impl ProvideCredential for StaticTokenCredentialProvider {
-    type Credential = Credential;
-
-    async fn provide_credential(
-        &self,
-        _: &Context,
-    ) -> reqsign_core::Result<Option<Self::Credential>> {
-        Ok(Some(Credential::with_token(Token {
-            access_token: self.token.clone(),
-            expires_at: None,
-        })))
-    }
-}
-
-// TODO(remove): drop this adapter once reqsign-google provides a built-in
-// file-path credential provider for explicit credential_path usage.
-// Tracking issue: https://github.com/apache/opendal-reqsign/issues/696
-#[derive(Clone, Debug)]
-struct PathCredentialProvider {
-    path: String,
-    scope: String,
-}
-
-impl PathCredentialProvider {
-    fn new(path: impl Into<String>, scope: impl Into<String>) -> Self {
-        Self {
-            path: path.into(),
-            scope: scope.into(),
-        }
-    }
-}
-
-#[async_trait::async_trait]
-impl ProvideCredential for PathCredentialProvider {
-    type Credential = Credential;
-
-    async fn provide_credential(
-        &self,
-        ctx: &Context,
-    ) -> reqsign_core::Result<Option<Self::Credential>> {
-        let content = String::from_utf8(ctx.file_read(&self.path).await?).map_err(|err| {
-            reqsign_core::Error::unexpected("credential file content is invalid utf-8")
-                .with_source(err)
-        })?;
-
-        StaticCredentialProvider::new(content)
-            .with_scope(&self.scope)
-            .provide_credential(ctx)
-            .await
-    }
-}
-
-#[derive(Debug, Deserialize)]
-struct VmMetadataTokenResponse {
-    access_token: String,
-    expires_in: u64,
-}
-
-// TODO(remove): drop this adapter once reqsign-google supports selecting
-// service account for VM metadata credential loading.
-// Tracking issue: https://github.com/apache/opendal-reqsign/issues/695
-#[derive(Clone, Debug)]
-struct ServiceAccountVmMetadataCredentialProvider {
-    service_account: String,
-    scope: String,
-}
-
-impl ServiceAccountVmMetadataCredentialProvider {
-    fn new(service_account: impl Into<String>, scope: impl Into<String>) -> Self {
-        Self {
-            service_account: service_account.into(),
-            scope: scope.into(),
-        }
-    }
-}
-
-#[async_trait::async_trait]
-impl ProvideCredential for ServiceAccountVmMetadataCredentialProvider {
-    type Credential = Credential;
-
-    async fn provide_credential(
-        &self,
-        ctx: &Context,
-    ) -> reqsign_core::Result<Option<Self::Credential>> {
-        let metadata_host = ctx
-            .env_var("GCE_METADATA_HOST")
-            .unwrap_or_else(|| "metadata.google.internal".to_string());
-
-        let url = format!(
-            "http://{metadata_host}/computeMetadata/v1/instance/service-accounts/{}/token?scopes={}",
-            self.service_account, self.scope
-        );
-
-        let req = http::Request::builder()
-            .method(http::Method::GET)
-            .uri(&url)
-            .header("Metadata-Flavor", "Google")
-            .body(Bytes::new())
-            .map_err(|err| {
-                reqsign_core::Error::unexpected("failed to build vm metadata request")
-                    .with_source(err)
-            })?;
-
-        let resp = ctx.http_send(req).await?;
-        if resp.status() != StatusCode::OK {
-            return Ok(None);
-        }
-
-        let resp: VmMetadataTokenResponse = serde_json::from_slice(resp.body()).map_err(|err| {
-            reqsign_core::Error::unexpected("failed to parse vm metadata token response")
-                .with_source(err)
-        })?;
-
-        Ok(Some(Credential::with_token(Token {
-            access_token: resp.access_token,
-            expires_at: Some(Timestamp::now() + Duration::from_secs(resp.expires_in)),
-        })))
-    }
-}
-
 impl Debug for GcsBuilder {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         f.debug_struct("GcsBuilder")
@@ -408,9 +265,11 @@ impl Builder for GcsBuilder {
         let mut envs = os_env.vars();
         envs.insert("GOOGLE_SCOPE".to_string(), scope.clone());
 
+        let info = Arc::new(AccessorInfo::default());
+
         let ctx = Context::new()
             .with_file_read(TokioFileRead)
-            .with_http_send(ReqwestHttpSend::new(GLOBAL_REQWEST_CLIENT.clone()))
+            .with_http_send(AccessorInfoHttpSend::new(info.clone()))
             .with_env(StaticEnv {
                 home_dir: os_env.home_dir(),
                 envs,
@@ -419,19 +278,15 @@ impl Builder for GcsBuilder {
         let mut default_credential = DefaultCredentialProvider::builder();
         #[cfg(target_arch = "wasm32")]
         {
-            default_credential = default_credential
-                .disable_env(true)
-                .disable_well_known(true);
+            default_credential = default_credential.no_env().no_well_known();
         }
 
         if self.config.disable_config_load {
-            default_credential = default_credential
-                .disable_env(true)
-                .disable_well_known(true);
+            default_credential = default_credential.no_env().no_well_known();
         }
 
         if self.config.disable_vm_metadata || self.config.service_account.is_some() {
-            default_credential = default_credential.disable_vm_metadata(true);
+            default_credential = default_credential.no_vm_metadata();
         }
 
         let mut credential_chain = ProvideCredentialChain::new().push(default_credential.build());
@@ -439,14 +294,16 @@ impl Builder for GcsBuilder {
         if !self.config.disable_vm_metadata {
             if let Some(service_account) = self.config.service_account.as_deref() {
                 credential_chain = credential_chain.push(
-                    ServiceAccountVmMetadataCredentialProvider::new(service_account, &scope),
+                    VmMetadataCredentialProvider::new()
+                        .with_scope(&scope)
+                        .with_service_account(service_account),
                 );
             }
         }
 
         if let Some(path) = self.config.credential_path.as_deref() {
             credential_chain =
-                credential_chain.push_front(PathCredentialProvider::new(path, scope.clone()));
+                credential_chain.push_front(FileCredentialProvider::new(path).with_scope(&scope));
         }
 
         if let Some(content) = self.config.credential.as_deref() {
@@ -456,8 +313,7 @@ impl Builder for GcsBuilder {
         }
 
         if let Some(token) = self.config.token.as_deref() {
-            credential_chain =
-                credential_chain.push_front(StaticTokenCredentialProvider::new(token));
+            credential_chain = credential_chain.push_front(TokenCredentialProvider::new(token));
         }
 
         if let Some(customized_credential_chain) = self.credential_provider_chain {
@@ -473,8 +329,7 @@ impl Builder for GcsBuilder {
         let backend = GcsBackend {
             core: Arc::new(GcsCore {
                 info: {
-                    let am = AccessorInfo::default();
-                    am.set_scheme(GCS_SCHEME)
+                    info.set_scheme(GCS_SCHEME)
                         .set_root(&root)
                         .set_name(bucket)
                         .set_native_capability(Capability {
@@ -528,7 +383,7 @@ impl Builder for GcsBuilder {
                             ..Default::default()
                         });
 
-                    am.into()
+                    info.clone()
                 },
                 endpoint,
                 bucket: bucket.to_string(),
diff --git a/core/services/ghac/Cargo.toml b/core/services/ghac/Cargo.toml
index a9f003abb..bb3efa2c5 100644
--- a/core/services/ghac/Cargo.toml
+++ b/core/services/ghac/Cargo.toml
@@ -38,8 +38,8 @@ log = { workspace = true }
 opendal-core = { path = "../../core", version = "0.55.0", default-features = false }
 opendal-service-azblob = { path = "../azblob", version = "0.55.0", default-features = false }
 prost = { version = "0.13", default-features = false }
-reqsign-azure-storage = { version = "2.0.2", default-features = false }
-reqsign-core = { version = "2.0.1", default-features = false }
+reqsign-azure-storage = { version = "3.0.0", default-features = false }
+reqsign-core = { version = "3.0.0", default-features = false }
 serde = { workspace = true, features = ["derive"] }
 serde_json = { workspace = true }
 sha2 = { workspace = true }
diff --git a/core/services/obs/Cargo.toml b/core/services/obs/Cargo.toml
index 3d828df60..2405f6bf5 100644
--- a/core/services/obs/Cargo.toml
+++ b/core/services/obs/Cargo.toml
@@ -36,10 +36,9 @@ http = { workspace = true }
 log = { workspace = true }
 opendal-core = { path = "../../core", version = "0.55.0", default-features = false }
 quick-xml = { workspace = true, features = ["serialize", "overlapped-lists"] }
-reqsign-core = "2.0.2"
-reqsign-file-read-tokio = "2.0.2"
-reqsign-http-send-reqwest = "2.0.1"
-reqsign-huaweicloud-obs = "2.0.2"
+reqsign-core = "3.0.0"
+reqsign-file-read-tokio = "3.0.0"
+reqsign-huaweicloud-obs = "3.0.0"
 serde = { workspace = true, features = ["derive"] }
 
 [dev-dependencies]
diff --git a/core/services/obs/src/backend.rs b/core/services/obs/src/backend.rs
index 42bcbe2ba..99c5fe2ca 100644
--- a/core/services/obs/src/backend.rs
+++ b/core/services/obs/src/backend.rs
@@ -30,7 +30,6 @@ use reqsign_core::OsEnv;
 use reqsign_core::ProvideCredentialChain;
 use reqsign_core::Signer;
 use reqsign_file_read_tokio::TokioFileRead;
-use reqsign_http_send_reqwest::ReqwestHttpSend;
 use reqsign_huaweicloud_obs::EnvCredentialProvider;
 use reqsign_huaweicloud_obs::RequestSigner;
 use reqsign_huaweicloud_obs::StaticCredentialProvider;
@@ -175,9 +174,11 @@ impl Builder for ObsBuilder {
         };
         debug!("backend use endpoint {}", &endpoint);
 
+        let info = Arc::new(AccessorInfo::default());
+
         let ctx = Context::new()
             .with_file_read(TokioFileRead)
-            .with_http_send(ReqwestHttpSend::new(GLOBAL_REQWEST_CLIENT.clone()))
+            .with_http_send(AccessorInfoHttpSend::new(info.clone()))
             .with_env(OsEnv);
 
         let mut provider = ProvideCredentialChain::new().push(EnvCredentialProvider::new());
@@ -201,8 +202,7 @@ impl Builder for ObsBuilder {
         Ok(ObsBackend {
             core: Arc::new(ObsCore {
                 info: {
-                    let am = AccessorInfo::default();
-                    am.set_scheme(OBS_SCHEME)
+                    info.set_scheme(OBS_SCHEME)
                         .set_root(&root)
                         .set_name(&bucket)
                         .set_native_capability(Capability {
@@ -251,7 +251,7 @@ impl Builder for ObsBuilder {
                             ..Default::default()
                         });
 
-                    am.into()
+                    info.clone()
                 },
                 bucket,
                 root,
diff --git a/core/services/oss/Cargo.toml b/core/services/oss/Cargo.toml
index 22ebd0192..183d24fea 100644
--- a/core/services/oss/Cargo.toml
+++ b/core/services/oss/Cargo.toml
@@ -36,10 +36,9 @@ http = { workspace = true }
 log = { workspace = true }
 opendal-core = { path = "../../core", version = "0.55.0", default-features = false }
 quick-xml = { workspace = true, features = ["serialize", "overlapped-lists"] }
-reqsign-aliyun-oss = { version = "2.0.2", default-features = false }
-reqsign-core = { version = "2.0.1", default-features = false }
-reqsign-file-read-tokio = { version = "2.0.1", default-features = false }
-reqsign-http-send-reqwest = { version = "2.0.1", default-features = false }
+reqsign-aliyun-oss = { version = "3.0.0", default-features = false }
+reqsign-core = { version = "3.0.0", default-features = false }
+reqsign-file-read-tokio = { version = "3.0.0", default-features = false }
 serde = { workspace = true, features = ["derive"] }
 
 [dev-dependencies]
diff --git a/core/services/oss/src/backend.rs b/core/services/oss/src/backend.rs
index c152872d7..82b10d5e3 100644
--- a/core/services/oss/src/backend.rs
+++ b/core/services/oss/src/backend.rs
@@ -33,7 +33,6 @@ use reqsign_core::ProvideCredentialChain;
 use reqsign_core::Signer;
 use reqsign_core::StaticEnv;
 use reqsign_file_read_tokio::TokioFileRead;
-use reqsign_http_send_reqwest::ReqwestHttpSend;
 
 use super::OSS_SCHEME;
 use super::config::OssConfig;
@@ -474,9 +473,11 @@ impl Builder for OssBuilder {
             assume_role = assume_role.with_role_session_name(role_session_name.clone());
         }
 
+        let info = Arc::new(AccessorInfo::default());
+
         let ctx = Context::new()
             .with_file_read(TokioFileRead)
-            .with_http_send(ReqwestHttpSend::new(GLOBAL_REQWEST_CLIENT.clone()))
+            .with_http_send(AccessorInfoHttpSend::new(info.clone()))
             .with_env(StaticEnv {
                 home_dir: os_env.home_dir(),
                 envs,
@@ -506,8 +507,7 @@ impl Builder for OssBuilder {
         Ok(OssBackend {
             core: Arc::new(OssCore {
                 info: {
-                    let am = AccessorInfo::default();
-                    am.set_scheme(OSS_SCHEME)
+                    info.set_scheme(OSS_SCHEME)
                         .set_root(&root)
                         .set_name(bucket)
                         .set_native_capability(Capability {
@@ -571,7 +571,7 @@ impl Builder for OssBuilder {
                             ..Default::default()
                         });
 
-                    am.into()
+                    info.clone()
                 },
                 root,
                 bucket: bucket.to_owned(),
diff --git a/core/services/s3/Cargo.toml b/core/services/s3/Cargo.toml
index 87bae334a..8adcb760a 100644
--- a/core/services/s3/Cargo.toml
+++ b/core/services/s3/Cargo.toml
@@ -39,14 +39,11 @@ log = { workspace = true }
 md-5 = "0.10"
 opendal-core = { path = "../../core", version = "0.55.0", default-features = false }
 quick-xml = { workspace = true, features = ["serialize", "overlapped-lists"] }
-reqsign-aws-v4 = { version = "2.0.1", default-features = false }
-reqsign-core = { version = "2.0.1", default-features = false }
-reqsign-file-read-tokio = { version = "2.0.1", default-features = false }
-reqsign-http-send-reqwest = { version = "2.0.1", default-features = false }
-reqwest = { version = "0.12.24", default-features = false, features = [
-  "stream",
-] }
+reqsign-aws-v4 = { version = "3.0.0", default-features = false }
+reqsign-core = { version = "3.0.0", default-features = false }
+reqsign-file-read-tokio = { version = "3.0.0", default-features = false }
 serde = { workspace = true, features = ["derive"] }
+url = { workspace = true }
 
 [dev-dependencies]
 pretty_assertions = "1"
diff --git a/core/services/s3/src/backend.rs b/core/services/s3/src/backend.rs
index 9c2fa68ad..26d8b4713 100644
--- a/core/services/s3/src/backend.rs
+++ b/core/services/s3/src/backend.rs
@@ -18,7 +18,6 @@
 use std::collections::HashMap;
 use std::fmt::Debug;
 use std::fmt::Write;
-use std::str::FromStr;
 use std::sync::Arc;
 use std::sync::LazyLock;
 
@@ -42,8 +41,7 @@ use reqsign_core::OsEnv;
 use reqsign_core::ProvideCredentialChain;
 use reqsign_core::Signer;
 use reqsign_file_read_tokio::TokioFileRead;
-use reqsign_http_send_reqwest::ReqwestHttpSend;
-use reqwest::Url;
+use url::Url;
 
 use crate::S3_SCHEME;
 use crate::config::S3Config;
@@ -59,8 +57,6 @@ use crate::writer::S3Writers;
 use opendal_core::raw::*;
 use opendal_core::*;
 
-static GLOBAL_REQWEST_CLIENT: LazyLock<reqwest::Client> = LazyLock::new(reqwest::Client::new);
-
 /// Allow constructing correct region endpoint if user gives a global endpoint.
 static ENDPOINT_TEMPLATES: LazyLock<HashMap<&'static str, &'static str>> = LazyLock::new(|| {
     let mut m = HashMap::new();
@@ -499,7 +495,7 @@ impl S3Builder {
         endpoint = endpoint.replace(&format!("//{bucket}."), "//");
 
         // Omit default ports if specified.
-        if let Ok(url) = Url::from_str(&endpoint) {
+        if let Ok(url) = Url::parse(&endpoint) {
             // Remove the trailing `/` of root path.
             endpoint = url.to_string().trim_end_matches('/').to_string();
         }
@@ -806,21 +802,23 @@ impl Builder for S3Builder {
         let endpoint = Self::build_endpoint(&config, &region);
         debug!("backend use endpoint: {endpoint}");
 
+        let info = Arc::new(AccessorInfo::default());
+
         // Create the context for reqsign-core
         let ctx = Context::new()
             .with_file_read(TokioFileRead)
-            .with_http_send(ReqwestHttpSend::new(GLOBAL_REQWEST_CLIENT.clone()))
+            .with_http_send(AccessorInfoHttpSend::new(info.clone()))
             .with_env(OsEnv);
 
         let mut provider = {
             let mut builder = DefaultCredentialProvider::builder();
 
             if config.disable_config_load {
-                builder = builder.disable_env(true).disable_profile(true);
+                builder = builder.no_env().no_profile();
             }
 
             if config.disable_ec2_metadata {
-                builder = builder.disable_imds(true);
+                builder = builder.no_imds();
             }
 
             ProvideCredentialChain::new().push(builder.build())
@@ -876,8 +874,7 @@ impl Builder for S3Builder {
         Ok(S3Backend {
             core: Arc::new(S3Core {
                 info: {
-                    let am = AccessorInfo::default();
-                    am.set_scheme(S3_SCHEME)
+                    info.set_scheme(S3_SCHEME)
                         .set_root(&root)
                         .set_name(bucket)
                         .set_native_capability(Capability {
@@ -950,7 +947,7 @@ impl Builder for S3Builder {
                             ..Default::default()
                         });
 
-                    am.into()
+                    info.clone()
                 },
                 bucket: bucket.to_string(),
                 endpoint,