Package Exports
- @paschendale/r2-presigned-url
- @paschendale/r2-presigned-url/dist/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@paschendale/r2-presigned-url) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
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-urlQuick 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 bucketcontentType(string): MIME type of the fileexpiresIn(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 IDR2_SECRET_ACCESS_KEY(string): Cloudflare R2 Secret Access KeyR2_ACCOUNT_ID(string): Cloudflare Account IDR2_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
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- 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