Skip to content

paschendale/r2-presigned-url

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

R2 Presigned URL Generator

A lightweight, zero-dependency TypeScript library for generating presigned URLs for Cloudflare R2 storage using AWS Signature Version 4. Compatible with Cloudflare Workers and Node.js environments.

Features

  • Zero Dependencies - Uses only Web Crypto API and built-in browser/Node.js APIs
  • Cloudflare Workers Compatible - No Node.js-specific dependencies
  • TypeScript Support - Full type definitions included
  • AWS Signature Version 4 - Standard-compliant signature generation
  • Multiple HTTP Methods - Support for PUT, GET, and POST requests
  • Comprehensive Validation - Input validation and error handling
  • Testing Utilities - Built-in test function for debugging

Installation

npm install r2-presigned-url

Quick Start

import { generateR2PresignedUrl, R2Credentials } from 'r2-presigned-url';

const credentials: R2Credentials = {
  R2_ACCESS_KEY_ID: 'your-access-key',
  R2_SECRET_ACCESS_KEY: 'your-secret-key',
  R2_ACCOUNT_ID: 'your-account-id',
  R2_BUCKET: 'my-bucket'
};

const url = await generateR2PresignedUrl(
  {
    key: 'uploads/file.jpg',
    contentType: 'image/jpeg',
    expiresIn: 3600 // 1 hour
  },
  credentials
);

console.log('Presigned URL:', url);

API Reference

generateR2PresignedUrl(options, credentials)

Generates a presigned URL for R2 storage operations.

Parameters

  • options (PresignedUrlOptions):

    • key (string): The object key (path) in the R2 bucket
    • contentType (string): MIME type of the file
    • expiresIn (number): URL expiration time in seconds (max 604800 = 7 days)
    • method (optional): HTTP method - 'PUT' (default), 'GET', or 'POST'
  • credentials (R2Credentials):

    • R2_ACCESS_KEY_ID (string): Cloudflare R2 Access Key ID
    • R2_SECRET_ACCESS_KEY (string): Cloudflare R2 Secret Access Key
    • R2_ACCOUNT_ID (string): Cloudflare Account ID
    • R2_BUCKET (optional): R2 Bucket name (defaults to 'development')

Returns

  • Promise<string>: The presigned URL

testPresignedUrlGeneration(credentials)

Tests the presigned URL generation with sample data.

Parameters

  • credentials (R2Credentials): R2 credentials to test with

Returns

  • Promise<TestResult>: Test results with success status and debug info

Usage Examples

Upload a File

import { generateR2PresignedUrl } from 'r2-presigned-url';

const uploadUrl = await generateR2PresignedUrl(
  {
    key: 'uploads/document.pdf',
    contentType: 'application/pdf',
    expiresIn: 1800 // 30 minutes
  },
  credentials
);

// Use the URL to upload the file
const response = await fetch(uploadUrl, {
  method: 'PUT',
  body: file,
  headers: {
    'Content-Type': 'application/pdf'
  }
});

Download a File

const downloadUrl = await generateR2PresignedUrl(
  {
    key: 'uploads/document.pdf',
    contentType: 'application/pdf',
    expiresIn: 3600,
    method: 'GET'
  },
  credentials
);

// Use the URL to download the file
const response = await fetch(downloadUrl);
const file = await response.blob();

Testing

import { testPresignedUrlGeneration } from 'r2-presigned-url';

const result = await testPresignedUrlGeneration(credentials);

if (result.success) {
  console.log('✅ Test passed!');
  console.log('Generated URL:', result.url);
  console.log('Signature:', result.debug?.signature);
} else {
  console.error('❌ Test failed:', result.error);
}

Cloudflare Workers Example

// workers/index.ts
import { generateR2PresignedUrl } from 'r2-presigned-url';

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    if (request.method === 'POST') {
      const { key, contentType } = await request.json();
      
      const credentials = {
        R2_ACCESS_KEY_ID: env.R2_ACCESS_KEY_ID,
        R2_SECRET_ACCESS_KEY: env.R2_SECRET_ACCESS_KEY,
        R2_ACCOUNT_ID: env.R2_ACCOUNT_ID,
        R2_BUCKET: env.R2_BUCKET
      };

      try {
        const url = await generateR2PresignedUrl(
          {
            key,
            contentType,
            expiresIn: 3600
          },
          credentials
        );

        return new Response(JSON.stringify({ url }), {
          headers: { 'Content-Type': 'application/json' }
        });
      } catch (error) {
        return new Response(
          JSON.stringify({ error: error.message }), 
          { status: 400, headers: { 'Content-Type': 'application/json' } }
        );
      }
    }

    return new Response('Method not allowed', { status: 405 });
  }
};

Environment Variables

For Cloudflare Workers, add these to your wrangler.toml:

[vars]
R2_ACCESS_KEY_ID = "your-access-key"
R2_SECRET_ACCESS_KEY = "your-secret-key"
R2_ACCOUNT_ID = "your-account-id"
R2_BUCKET = "your-bucket-name"

Error Handling

The library throws descriptive errors for common issues:

try {
  const url = await generateR2PresignedUrl(options, credentials);
} catch (error) {
  if (error.message.includes('Missing required R2 credentials')) {
    // Handle missing credentials
  } else if (error.message.includes('Invalid parameters')) {
    // Handle invalid parameters
  } else {
    // Handle other errors
  }
}

Browser Compatibility

This library uses the Web Crypto API, which is supported in:

  • Chrome 37+
  • Firefox 34+
  • Safari 11+
  • Edge 12+
  • Node.js 15+

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests if applicable
  5. Submit a pull request

License

MIT License - see LICENSE file for details.

Changelog

1.0.0

  • Initial release
  • AWS Signature Version 4 implementation
  • Cloudflare Workers compatibility
  • TypeScript support
  • Comprehensive error handling

About

Generate presigned URLs for Cloudflare R2 storage using AWS Signature Version 4 - Compatible with Cloudflare Workers

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published