Getting Started
Five minutes from an empty project to a signed AWS request. The same shape works for every provider — only the entry point differs.
1. Install
Add the reqsign facade with the feature for each provider you need
(features are additive):
cargo add reqsign --features aws
cargo add tokio --features full
cargo add http anyhow
| Feature | Enables |
|---|---|
aws | AWS SigV4 (alias of aws-v4) |
aws-v4a | AWS SigV4a multi-region signing |
azure | Azure Storage |
google | Google Cloud |
google-credential-access-boundary-client-side | Client-side CAB downscoping (implies google) |
aliyun | Aliyun OSS |
huaweicloud | Huawei Cloud OBS |
oracle | Oracle Cloud |
tencent | Tencent COS |
volcengine | Volcengine TOS |
full | Everything above |
The default default-context feature wires a ready-to-use runtime (Tokio
file reading, reqwest HTTP, Tokio command execution). Keep it unless you are
bringing your own runtime. Requires
Rust 1.86.0+.
2. Sign your first request
This is the repository's compiled example — CI builds it on every commit:
use anyhow::Result;
#[tokio::main]
async fn main() -> Result<()> {
use reqsign::aws;
// Create a default signer for S3 in us-east-1
let signer = aws::default_signer("s3", "us-east-1");
// Build a request
let mut req = http::Request::builder()
.method(http::Method::GET)
.uri("https://s3.amazonaws.com/my-bucket/my-object")
.body(())
.unwrap()
.into_parts()
.0;
// Sign the request
signer.sign(&mut req, None).await?;
// Execute the request would require rebuilding with body
// In real usage, you'd use your HTTP client here
println!("Request signed successfully!");
Ok(())
}
Three things happen here:
aws::default_signer("s3", "us-east-1")composes the default runtime context with AWS's full credential chain — environment variables, shared profiles, SSO, ECS, IMDS, and more. See Loading credentials.- The request is built with the plain
httpcrate. Reqsign signshttp::request::Partsdirectly — there is no wrapper client to adopt. signer.sign(&mut req, None).await?mutates the request head in place, adding theAuthorizationheader and companions. PassingSome(duration)instead selects query authentication where the provider supports it — see Presigning.
3. Run it
AWS_ACCESS_KEY_ID=AKIDEXAMPLE \
AWS_SECRET_ACCESS_KEY=example-secret \
cargo run
The example signs the request and prints a confirmation; sending it is your HTTP client's job. Any placeholder credentials produce a structurally valid signature — the service rejects them, but the wire format is real.
Every provider, one pattern
Swap the entry point and the rest of the code stays the same. Each entry composes that provider's own credential chain — the provider pages document exactly which sources:
| Provider | Entry |
|---|---|
| AWS SigV4 | aws::default_signer(service, region) |
| AWS SigV4a | aws::v4a::default_signer(service, region_set) |
| Azure Storage | azure::default_signer() |
| Google Cloud | google::default_signer(service) |
| Aliyun OSS | aliyun::default_signer(bucket) |
| Huawei Cloud OBS | huaweicloud::default_signer(bucket) |
| Oracle Cloud | oracle::default_signer() |
| Tencent COS | tencent::default_signer() |
| Volcengine TOS | volcengine::default_signer(region) |
A default signer is an ordinary Signer: replace any component and keep the
rest —
async fn main() -> anyhow::Result<()> {
use reqsign::aws::{self, StaticCredentialProvider};
let signer = aws::default_signer("s3", "us-east-1").with_credential_provider(
StaticCredentialProvider::new("AKIDEXAMPLE", "example-secret-key"),
);
let provider = reqsign::aws::DefaultCredentialProvider::new().push_front(
StaticCredentialProvider::new("AKIDEXAMPLE", "example-secret-key"),
);
let _custom_chain_signer =
aws::default_signer("s3", "us-east-1").with_credential_provider(provider);
let mut req = http::Request::get("https://s3.amazonaws.com/my-bucket/my-object")
.body(())?
.into_parts()
.0;
signer.sign(&mut req, None).await?;
assert!(req.headers.contains_key("authorization"));
Ok(())
}
Where to go next
- Wire up credentials your way: Loading credentials.
- Hand out URLs instead of headers: Presigning.
- Understand the pieces you just used: Architecture.
- Check what your provider supports: provider matrix.