Skip to content

Commit

Permalink
feat: Allow reqsign to be used in wasm (#397)
Browse files Browse the repository at this point in the history
Signed-off-by: Xuanwo <github@xuanwo.io>
  • Loading branch information
Xuanwo authored Dec 21, 2023
1 parent bea67b4 commit a746dd5
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 11 deletions.
9 changes: 9 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,15 @@ jobs:
with:
command: build

build_under_wasm:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build
run: |
rustup target add wasm32-unknown-unknown
cargo build --target wasm32-unknown-unknown
build_all_features:
runs-on: ${{ matrix.os }}
strategy:
Expand Down
10 changes: 8 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,8 @@ chrono = "0.4.24"
form_urlencoded = "1"
hex = "0.4"
hmac = "0.12"
home = "0.5"
http = "0.2"
jsonwebtoken = { version = "9", optional = true }
jsonwebtoken = { version = "9.2", optional = true }
log = "0.4"
once_cell = "1"
percent-encoding = "2"
Expand All @@ -78,8 +77,15 @@ serde = { version = "1", features = ["derive"], optional = true }
serde_json = { version = "1", optional = true }
sha1 = "0.10"
sha2 = { version = "0.10", features = ["oid"] }

[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
home = "0.5"
tokio = { version = "1", features = ["fs"], optional = true }

[target.'cfg(target_arch = "wasm32")'.dependencies]
getrandom = { version = "0.2", features = ["js"] }
tokio = { version = "1", optional = true }

[dev-dependencies]
aws-sigv4 = "0.56"
criterion = { version = "0.5", features = ["async_tokio", "html_reports"] }
Expand Down
10 changes: 10 additions & 0 deletions src/aws/config.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
use std::collections::HashMap;
use std::env;
#[cfg(not(target_arch = "wasm32"))]
use std::fs;

#[cfg(not(target_arch = "wasm32"))]
use anyhow::anyhow;
#[cfg(not(target_arch = "wasm32"))]
use anyhow::Result;
#[cfg(not(target_arch = "wasm32"))]
use ini::Ini;
#[cfg(not(target_arch = "wasm32"))]
use log::debug;

use super::constants::*;
#[cfg(not(target_arch = "wasm32"))]
use crate::dirs::expand_homedir;

/// Config for aws services.
Expand Down Expand Up @@ -159,6 +165,7 @@ impl Config {
///
/// If the env var AWS_PROFILE is set, this profile will be used,
/// otherwise the contents of `self.profile` will be used.
#[cfg(not(target_arch = "wasm32"))]
pub fn from_profile(mut self) -> Self {
// self.profile is checked by the two load methods.
if let Ok(profile) = env::var(AWS_PROFILE) {
Expand Down Expand Up @@ -193,6 +200,7 @@ impl Config {
/// - `aws_access_key_id`
/// - `aws_secret_access_key`
/// - `aws_session_token`
#[cfg(not(target_arch = "wasm32"))]
fn load_via_profile_shared_credentials_file(&mut self) -> Result<()> {
let path = expand_homedir(&self.shared_credentials_file)
.ok_or_else(|| anyhow!("expand homedir failed"))?;
Expand All @@ -218,6 +226,7 @@ impl Config {
Ok(())
}

#[cfg(not(target_arch = "wasm32"))]
fn load_via_profile_config_file(&mut self) -> Result<()> {
let path =
expand_homedir(&self.config_file).ok_or_else(|| anyhow!("expand homedir failed"))?;
Expand Down Expand Up @@ -268,6 +277,7 @@ mod tests {
use tempfile::tempdir;

#[test]
#[cfg(not(target_arch = "wasm32"))]
fn test_config_from_profile_shared_credentials() -> Result<()> {
let _ = env_logger::builder().is_test(true).try_init();

Expand Down
27 changes: 18 additions & 9 deletions src/aws/credential.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use std::fmt::Write;
use std::fs;
use std::sync::Arc;
use std::sync::Mutex;
use std::time::Duration;

use anyhow::anyhow;
use anyhow::Result;
Expand Down Expand Up @@ -59,7 +58,8 @@ impl Credential {
}

/// Loader trait will try to load credential from different sources.
#[async_trait]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
pub trait CredentialLoad: 'static + Send + Sync {
/// Load credential from sources.
///
Expand Down Expand Up @@ -246,7 +246,8 @@ impl DefaultLoader {
}
}

#[async_trait]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
impl CredentialLoad for DefaultLoader {
async fn load_credential(&self, _: Client) -> Result<Option<Credential>> {
self.load().await
Expand Down Expand Up @@ -332,14 +333,20 @@ impl IMDSv2Loader {
}

let url = "http://169.254.169.254/latest/api/token";
let req = self
#[allow(unused_mut)]
let mut req = self
.client
.put(url)
.header(CONTENT_LENGTH, "0")
// 21600s (6h) is recommended by AWS.
.header("x-aws-ec2-metadata-token-ttl-seconds", "21600")
// Set timeout to 1s to avoid hanging on non-s3 env.
.timeout(Duration::from_secs(1));
.header("x-aws-ec2-metadata-token-ttl-seconds", "21600");

// Set timeout to 1s to avoid hanging on non-s3 env.
#[cfg(not(target_arch = "wasm32"))]
{
req = req.timeout(std::time::Duration::from_secs(1));
}

let resp = req.send().await?;
if resp.status() != http::StatusCode::OK {
let content = resp.text().await?;
Expand All @@ -359,7 +366,8 @@ impl IMDSv2Loader {
}
}

#[async_trait]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
impl CredentialLoad for IMDSv2Loader {
async fn load_credential(&self, _: Client) -> Result<Option<Credential>> {
self.load().await
Expand Down Expand Up @@ -483,7 +491,8 @@ impl AssumeRoleLoader {
}
}

#[async_trait]
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
impl CredentialLoad for AssumeRoleLoader {
async fn load_credential(&self, _: Client) -> Result<Option<Credential>> {
self.load().await
Expand Down
1 change: 1 addition & 0 deletions src/dirs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
/// - If path not starts with `~/` or `~\\`, returns `Some(path)` directly.
/// - Otherwise, replace `~` with home dir instead.
/// - If home_dir is not found, returns `None`.
#[cfg(not(target_arch = "wasm32"))]
pub fn expand_homedir(path: &str) -> Option<String> {
if !path.starts_with("~/") && !path.starts_with("~\\") {
Some(path.to_string())
Expand Down

0 comments on commit a746dd5

Please sign in to comment.