From 6e3993c1dcc16312cb0f1aa1acb353cdf85789b4 Mon Sep 17 00:00:00 2001 From: cayter Date: Tue, 17 Jun 2025 18:29:36 +0800 Subject: [PATCH] feat: add AWS_S3_FORCE_PATH_STYLE environment variable support ## Summary Adds support for the `AWS_S3_FORCE_PATH_STYLE` environment variable to enable path-style addressing for S3-compatible services. ## Changes - Modified `s3_client()` function to check for `AWS_S3_FORCE_PATH_STYLE` environment variable - When set to "true", configures the S3 client with `force_path_style(true)` - Added `Config` import from `aws_sdk_s3` ## Why This enables Convex to work with S3-compatible services like MinIO, LocalStack, and other object storage providers that require path-style addressing (`https://s3.amazonaws.com/bucket/key` instead of `https://bucket.s3.amazonaws.com/key`). ## Testing - [ ] Existing S3 functionality remains unchanged when environment variable is not set - [ ] Path-style addressing works when `AWS_S3_FORCE_PATH_STYLE=true` is set --- crates/aws_s3/src/storage.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/crates/aws_s3/src/storage.rs b/crates/aws_s3/src/storage.rs index a031489b2..e8ab58954 100644 --- a/crates/aws_s3/src/storage.rs +++ b/crates/aws_s3/src/storage.rs @@ -157,12 +157,24 @@ async fn s3_client() -> Result { static S3_CLIENT: tokio::sync::OnceCell = tokio::sync::OnceCell::const_new(); let client = S3_CLIENT .get_or_try_init(|| async { - let config = must_s3_config_from_env() + let aws_config = must_s3_config_from_env() .context("AWS env variables are required when using S3 storage")? .retry_config(RetryConfig::standard()) .load() .await; - anyhow::Ok(Client::new(&config)) + + // Build S3 config with optional force path style + let mut s3_config_builder = aws_sdk_s3::Config::builder().from(&aws_config); + + // Check for AWS_S3_FORCE_PATH_STYLE environment variable + if let Ok(force_path_style) = env::var("AWS_S3_FORCE_PATH_STYLE") { + if force_path_style.to_lowercase() == "true" { + s3_config_builder = s3_config_builder.force_path_style(true); + } + } + + let s3_config = s3_config_builder.build(); + anyhow::Ok(Client::from_conf(s3_config)) }) .await? .clone();