Last active
February 15, 2024 17:44
-
-
Save toddlers/2b300e007d2bfbfa5f152f3dba1cfb22 to your computer and use it in GitHub Desktop.
s3 presigned urls
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[package] | |
name = "s3_presign" | |
version = "0.1.0" | |
edition = "2021" | |
# Starting in Rust 1.62 you can use `cargo add` to add dependencies | |
# to your project. | |
# | |
# If you're using an older Rust version, | |
# download cargo-edit(https://github.com/killercup/cargo-edit#installation) | |
# to install the `add` subcommand. | |
# | |
# Running `cargo add DEPENDENCY_NAME` will | |
# add the latest version of a dependency to the list, | |
# and it will keep the alphabetic ordering for you. | |
[dependencies] | |
aws-config = "1.1.5" | |
aws-sdk-s3 = "1.15.0" | |
aws_lambda_events = { version = "0.14.0", default-features = false, features = ["cloudwatch_events"] } | |
lambda_runtime = "0.9.2" | |
serde = "1.0.196" | |
tokio = { version = "1", features = ["macros"] } | |
tracing = { version = "0.1", features = ["log"] } | |
tracing-subscriber = { version = "0.3", default-features = false, features = ["env-filter", "fmt"] } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// lambda to generate a presigned url for an s3 object | |
use aws_config::meta::region::RegionProviderChain; | |
use aws_config::BehaviorVersion; | |
use aws_sdk_s3::presigning::PresigningConfig; | |
use aws_sdk_s3::Client as S3Client; | |
use aws_sdk_s3::{config::Region, meta::PKG_VERSION, Client}; | |
use lambda_runtime::{run, service_fn, Error, LambdaEvent}; | |
use serde::{Deserialize, Serialize}; | |
use std::time::Duration; | |
use tracing_subscriber::filter::{EnvFilter, LevelFilter}; | |
#[derive(Debug, Deserialize)] | |
struct Request { | |
/// name of the bucket | |
bucket: String, | |
/// The object key | |
object: String, | |
/// lifetime | |
expires_in: Option<u64>, | |
/// verbose | |
verbose: bool, | |
/// region | |
region_name: Option<String>, | |
} | |
#[derive(Serialize)] | |
struct Response { | |
req_id: String, | |
uri: String, | |
} | |
async fn put_object(event: LambdaEvent<Request>) -> Result<Response, Error> { | |
let client = create_s3_client(&event).await.unwrap(); | |
let expires_in = Duration::from_secs(event.payload.expires_in.unwrap_or(900)); | |
let bucket_name = &event.payload.bucket; | |
let object_name = &event.payload.object; | |
let presigned_request = client | |
.get_object() | |
.bucket(bucket_name) | |
.key(object_name) | |
.presigned(PresigningConfig::expires_in(expires_in)?) | |
.await?; | |
println!("Object URI: {}", presigned_request.uri()); | |
let rsp = Response { | |
req_id: event.context.request_id, | |
uri: presigned_request.uri().to_string(), | |
}; | |
println!(); | |
if event.payload.verbose { | |
println!("S3 client version: {}", PKG_VERSION); | |
println!("Bucket: {}", &bucket_name); | |
println!("Object: {}", &object_name); | |
println!("Expires in: {:?} seconds", expires_in); | |
println!(); | |
} | |
Ok(rsp) | |
} | |
// Function to create the S3 client | |
async fn create_s3_client(event: &LambdaEvent<Request>) -> Result<S3Client, String> { | |
let region_name = event.payload.region_name.clone(); | |
let region_provider = RegionProviderChain::first_try(region_name.map(Region::new)) | |
.or_default_provider() | |
.or_else(Region::new("eu-west-1")); | |
let shared_config = aws_config::defaults(BehaviorVersion::v2023_11_09()) | |
.region(region_provider) | |
.load() | |
.await; | |
println!("Region: {}", shared_config.region().unwrap()); | |
let client = Client::new(&shared_config); | |
Ok(client) | |
} | |
#[tokio::main] | |
async fn main() -> Result<(), Error> { | |
tracing_subscriber::fmt() | |
.with_env_filter( | |
EnvFilter::builder() | |
.with_default_directive(LevelFilter::INFO.into()) | |
.from_env_lossy(), | |
) | |
.with_target(false) | |
.without_time() | |
.init(); | |
let func = | |
service_fn(move |event: LambdaEvent<Request>| async move { put_object(event).await }); | |
run(func).await?; | |
Ok(()) | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use aws_config::BehaviorVersion; | |
use aws_sdk_s3::presigning::PresigningConfig; | |
use aws_sdk_s3::Client as S3Client; | |
use lambda_runtime::{run, service_fn, Error, LambdaEvent}; | |
use serde::{Deserialize, Serialize}; | |
use std::time::Duration; | |
use tracing_subscriber::filter::{EnvFilter, LevelFilter}; | |
#[derive(Debug, Deserialize)] | |
struct Request { | |
/// name of the bucket | |
bucket: String, | |
/// The object key | |
object: String, | |
/// lifetime | |
expires_in: Option<u64>, | |
/// verbose | |
verbose: bool, | |
} | |
#[derive(Serialize)] | |
struct Response { | |
req_id: String, | |
uri: String, | |
} | |
async fn put_object( | |
event: LambdaEvent<Request>, | |
client: &S3Client, | |
) -> Result<Response, Error> { | |
let expires_in = Duration::from_secs(event.payload.expires_in.unwrap_or(900)); | |
let bucket_name = &event.payload.bucket; | |
let object_name = &event.payload.object; | |
let presigned_request = client | |
.put_object() | |
.bucket(bucket_name) | |
.key(object_name) | |
.presigned(PresigningConfig::expires_in(expires_in)?) | |
.await?; | |
println!("Object URI: {}", presigned_request.uri()); | |
let rsp = Response { | |
req_id: event.context.request_id, | |
uri: presigned_request.uri().to_string(), | |
}; | |
println!(); | |
if event.payload.verbose { | |
println!("Bucket: {}", bucket_name); | |
println!("Object: {}", object_name); | |
println!("Expires in: {:?} seconds", expires_in); | |
println!(); | |
} | |
Ok(rsp) | |
} | |
#[tokio::main] | |
async fn main() -> Result<(), Error> { | |
tracing_subscriber::fmt() | |
.with_env_filter( | |
EnvFilter::builder() | |
.with_default_directive(LevelFilter::INFO.into()) | |
.from_env_lossy(), | |
) | |
.with_target(false) | |
.without_time() | |
.init(); | |
let shared_config = aws_config::load_defaults(BehaviorVersion::v2023_11_09()).await; | |
let s3_client = S3Client::new(&shared_config); | |
let client_ref = &s3_client; | |
let func = service_fn(move |event: LambdaEvent<Request>| async move { put_object(event, client_ref).await }); | |
println!("Region: {}", shared_config.region().unwrap()); | |
run(func).await?; | |
Ok(()) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment