Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
209 changes: 209 additions & 0 deletions src/content/docs/r2/examples/aws/aws-sdk-rust.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
---
title: aws-sdk-rust
pcx_content_type: example
---

import { Render } from "~/components";

<Render file="keys" />
<br />

This example uses the [aws-sdk-s3](https://crates.io/crates/aws-sdk-s3) crate from the [AWS SDK for Rust](https://github.com/awslabs/aws-sdk-rust). You must pass in the R2 configuration credentials when instantiating your `S3` client:

:::note[Compatibility]
Client versions may introduce modifications to the default checksum behavior that could be incompatible with R2 APIs.

If you encounter checksum-related errors, add the following to your config:

```rust
.request_checksum_calculation(RequestChecksumCalculation::WhenRequired)
.response_checksum_validation(ResponseChecksumValidation::WhenRequired)
```

:::

## Basic Usage

```rust
use aws_sdk_s3 as s3;
use aws_smithy_types::date_time::Format::DateTime;

#[tokio::main]
async fn main() -> Result<(), s3::Error> {
let bucket_name = "sdk-example";
let account_id = "<accountid>";
let access_key_id = "<access_key_id>";
let access_key_secret = "<access_key_secret>";

// Configure the client
let config = aws_config::from_env()
.endpoint_url(format!("https://{}.r2.cloudflarestorage.com", account_id))
.credentials_provider(aws_sdk_s3::config::Credentials::new(
access_key_id,
access_key_secret,
None, // session token is not used with R2
None,
"R2",
))
.region("auto")
.load()
.await;

let client = s3::Client::new(&config);

// List buckets
let list_buckets_output = client.list_buckets().send().await?;

println!("Buckets:");
for bucket in list_buckets_output.buckets() {
println!(" - {}: {}",
bucket.name().unwrap_or_default(),
bucket.creation_date().map_or_else(
|| "Unknown creation date".to_string(),
|date| date.fmt(DateTime).unwrap()
)
);
}

// List objects in a specific bucket
let list_objects_output = client
.list_objects_v2()
.bucket(bucket_name)
.send()
.await?;

println!("\nObjects in {}:", bucket_name);
for object in list_objects_output.contents() {
println!(" - {}: {} bytes, last modified: {}",
object.key().unwrap_or_default(),
object.size().unwrap_or_default(),
object.last_modified().map_or_else(
|| "Unknown".to_string(),
|date| date.fmt(DateTime).unwrap()
)
);
}

Ok(())
}
```

## Upload Objects

To upload an object to R2:

```rust
use aws_sdk_s3::primitives::ByteStream;
use std::path::Path;

async fn upload_object(
client: &s3::Client,
bucket: &str,
key: &str,
file_path: &str,
) -> Result<(), s3::Error> {
let body = ByteStream::from_path(Path::new(file_path)).await.unwrap();

client
.put_object()
.bucket(bucket)
.key(key)
.body(body)
.send()
.await?;

println!("Uploaded {} to {}/{}", file_path, bucket, key);
Ok(())
}
```

## Download Objects

To download an object from R2:

```rust
use std::fs;
use std::io::Write;

async fn download_object(
client: &s3::Client,
bucket: &str,
key: &str,
output_path: &str,
) -> Result<(), Box<dyn std::error::Error>> {
let resp = client
.get_object()
.bucket(bucket)
.key(key)
.send()
.await?;

let data = resp.body.collect().await?;
let bytes = data.into_bytes();

let mut file = fs::File::create(output_path)?;
file.write_all(&bytes)?;

println!("Downloaded {}/{} to {}", bucket, key, output_path);
Ok(())
}
```

## Generate Presigned URLs

You can also generate presigned links that can be used to temporarily share public read or write access to a bucket.

```rust
use aws_sdk_s3::presigning::PresigningConfig;
use std::time::Duration;

async fn generate_get_presigned_url(
client: &s3::Client,
bucket: &str,
key: &str,
expires_in: Duration,
) -> Result<String, s3::Error> {
let presigning_config = PresigningConfig::expires_in(expires_in)?;

// Generate a presigned URL for GET (download)
let presigned_get_request = client
.get_object()
.bucket(bucket)
.key(key)
.presigned(presigning_config)
.await?;

Ok(presigned_get_request.uri().to_string())
}

async fn generate_upload_presigned_url(
client: &s3::Client,
bucket: &str,
key: &str,
expires_in: Duration,
) -> Result<String, s3::Error> {
let presigning_config = PresigningConfig::expires_in(expires_in)?;

// Generate a presigned URL for PUT (upload)
let presigned_put_request = client
.put_object()
.bucket(bucket)
.key(key)
.presigned(presigning_config)
.await?;

Ok(presigned_put_request.uri().to_string())
}
```

You can use these presigned URLs with any HTTP client. For example, to upload a file using the PUT URL:

```bash
curl -X PUT "https://<your-presigned-put-url>" -H "Content-Type: application/octet-stream" --data-binary "@local-file.txt"
```

To download a file using the GET URL:

```bash
curl -X GET "https://<your-presigned-get-url>" -o downloaded-file.txt
```