Skip to main content

Overview

The R2Credentials struct stores authentication credentials and configuration for connecting to a Cloudflare R2 bucket. It provides computed properties for endpoint URLs and methods for generating public URLs for uploaded objects.

Properties

id
UUID
required
Unique identifier for this credential set
accountId
String
required
Cloudflare account ID used to construct the R2 endpoint URL
accessKeyId
String
required
R2 access key ID for S3-compatible authentication
secretAccessKey
String
required
R2 secret access key for S3-compatible authentication
bucketName
String
required
Name of the R2 bucket to use for storage operations
customDomain
String?
Optional custom domain for public URLs. If provided, public URLs will use this domain instead of the default R2 endpoint
isEmpty
Bool
Returns true if any required credential fields are empty
endpoint
URL
The S3-compatible endpoint URL for this R2 account, formatted as:
https://{accountId}.r2.cloudflarestorage.com

Methods

publicURL(forKey:)

Constructs the public URL for an uploaded object.
key
String
required
The object key (path) in the R2 bucket
Returns: URL - The public URL for accessing the object Behavior:
  • If customDomain is set, returns {customDomain}/{key}
  • Otherwise, returns {endpoint}/{bucketName}/{key}

Source Code

R2Credentials.swift
import Foundation

struct R2Credentials: Sendable, Codable, Equatable, Identifiable {
    var id: UUID
    var accountId: String
    var accessKeyId: String
    var secretAccessKey: String
    var bucketName: String
    var customDomain: String?

    var isEmpty: Bool {
        accountId.isEmpty || accessKeyId.isEmpty || secretAccessKey.isEmpty || bucketName.isEmpty
    }

    init(
        id: UUID = UUID(),
        accountId: String,
        accessKeyId: String,
        secretAccessKey: String,
        bucketName: String,
        customDomain: String? = nil
    ) {
        self.id = id
        self.accountId = accountId
        self.accessKeyId = accessKeyId
        self.secretAccessKey = secretAccessKey
        self.bucketName = bucketName
        self.customDomain = customDomain
    }

    /// S3-compatible endpoint for this R2 account
    var endpoint: URL {
        URL(string: "https://\(accountId).r2.cloudflarestorage.com")!
    }

    /// Constructs the public URL for an uploaded object key
    func publicURL(forKey key: String) -> URL {
        if let customDomain, !customDomain.isEmpty,
           let base = URL(string: customDomain) {
            return base.appendingPathComponent(key)
        }
        return endpoint
            .appendingPathComponent(bucketName)
            .appendingPathComponent(key)
    }
}

Protocols

  • Sendable - Thread-safe value type
  • Codable - Can be encoded/decoded to/from JSON or other formats
  • Equatable - Can be compared for equality
  • Identifiable - Has a unique id property

Usage Example

let credentials = R2Credentials(
    accountId: "abc123",
    accessKeyId: "your-access-key",
    secretAccessKey: "your-secret-key",
    bucketName: "my-bucket",
    customDomain: "https://cdn.example.com"
)

// Get the S3 endpoint
let endpoint = credentials.endpoint
// https://abc123.r2.cloudflarestorage.com

// Generate a public URL
let publicURL = credentials.publicURL(forKey: "images/photo.jpg")
// https://cdn.example.com/images/photo.jpg