### Example POST Request to Storage Transfer Worker Source: https://github.com/api-grip/storage-transfer-worker/blob/main/README.md Example `curl` command demonstrating how to send a POST request to the Storage Transfer Worker. It includes the necessary `X-Signature` and `Content-Type` headers, along with the JSON payload containing the source URL and timestamp. ```bash curl -X POST https://your-worker.workers.dev \ -H "X-Signature: BASE64_SIGNATURE" \ -H "Content-Type: application/json" \ -d '{ "sourceUrl": "https://example.com/video.mp4", "timestamp": 1234567890123 }' ``` -------------------------------- ### Deploy Storage Transfer Worker Source: https://github.com/api-grip/storage-transfer-worker/blob/main/README.md Commands to install dependencies and deploy the Storage Transfer Worker using pnpm. Assumes pnpm is the package manager. ```bash pnpm install pnpm run deploy ``` -------------------------------- ### Deploying Storage Transfer Worker with Wrangler CLI Source: https://context7.com/api-grip/storage-transfer-worker/llms.txt Provides commands to deploy the worker to Cloudflare. It covers installing dependencies, creating an R2 bucket, running a local development server, deploying the worker, and verifying the deployment with a sample curl request. ```bash # 1. Install dependencies pnpm install # 2. Create R2 bucket for storage wrangler r2 bucket create your-bucket-name # 3. Run local development server pnpm run dev # Worker running at http://localhost:8787 # 4. Deploy to Cloudflare Workers pnpm run deploy # Published storage-transfer (https://storage-transfer.your-subdomain.workers.dev) # 5. Verify deployment curl -X POST https://storage-transfer.your-subdomain.workers.dev \ -H "Content-Type: application/json" \ -d '{"sourceUrl":"test"}' # Expected: {"success":false,"error":"Missing X-Signature header"} ``` -------------------------------- ### Environment Configuration Source: https://context7.com/api-grip/storage-transfer-worker/llms.txt Details the environment variables and R2 bucket binding required for configuring the Storage Transfer Worker, typically set in `wrangler.toml`. ```APIDOC ## Environment Configuration ### Description Configures the worker with R2 bucket binding, public URL prefix, and platform public key for signature verification. These are set in `wrangler.toml` and automatically injected by Cloudflare Workers runtime. ### Wrangler.toml Configuration ```toml name = "storage-transfer" main = "src/index.ts" compatibility_date = "2024-01-01" # R2 bucket binding for file storage [[r2_buckets]] binding = "BUCKET" bucket_name = "your-bucket-name" # Environment variables [vars] # Public CDN URL prefix for stored objects PUBLIC_URL = "https://cdn.your-domain.com" # API Grip platform public key (Ed25519, base64-encoded) # Default key for API Grip platform - change only if using custom signing PLATFORM_PUBLIC_KEY = "0uvFzFZYIqivaU6y4qvuHSb+Axj+Mj5aCP/49dekSIM=" # Optional: Custom domain routing # routes = [ # { pattern = "storage-transfer.your-domain.com", custom_domain = true } # ] ``` ### Environment Variables - **BUCKET**: Binding name for the R2 bucket where files will be stored. - **PUBLIC_URL**: The base URL for accessing stored files via the CDN. - **PLATFORM_PUBLIC_KEY**: The base64-encoded Ed25519 public key of the API Grip platform used for signature verification. ``` -------------------------------- ### Cloudflare Worker Environment Configuration (wrangler.toml) Source: https://context7.com/api-grip/storage-transfer-worker/llms.txt Configures the Cloudflare Worker using `wrangler.toml`. It specifies the worker's name, entry point, and compatibility date. Crucially, it sets up R2 bucket binding, defines the public CDN URL prefix, and includes the platform's public key for Ed25519 signature verification. ```toml # wrangler.toml configuration name = "storage-transfer" main = "src/index.ts" compatibility_date = "2024-01-01" # R2 bucket binding for file storage [[r2_buckets]] binding = "BUCKET" bucket_name = "your-bucket-name" # Environment variables [vars] # Public CDN URL prefix for stored objects PUBLIC_URL = "https://cdn.your-domain.com" # API Grip platform public key (Ed25519, base64-encoded) # Default key for API Grip platform - change only if using custom signing PLATFORM_PUBLIC_KEY = "0uvFzFZYIqivaU6y4qvuHSb+Axj+Mj5aCP/49dekSIM=" # Optional: Custom domain routing # routes = [ # { pattern = "storage-transfer.your-domain.com", custom_domain = true } # ] ``` -------------------------------- ### Transfer File to R2 Storage using cURL Source: https://context7.com/api-grip/storage-transfer-worker/llms.txt Demonstrates how to transfer a file to R2 storage using a cURL command. It includes the necessary headers for content type and signature, along with a JSON payload containing the source URL, timestamp, and audience. Error responses for invalid signatures, expired requests, and fetch failures are also shown. ```bash # Transfer a video file to R2 storage curl -X POST https://storage-transfer.your-domain.workers.dev \ -H "Content-Type: application/json" \ -H "X-Signature: BASE64_ED25519_SIGNATURE_HERE" \ -d '{ "sourceUrl": "https://example.com/assets/video.mp4", "timestamp": 1704067200000, "audience": "storage-transfer.your-domain.workers.dev" }' # Success Response (200 OK): # { # "success": true, # "url": "https://cdn.example.com/assets/video.mp4", # "size": 15728640, # "contentType": "video/mp4" # } # Error Response - Invalid Signature (401 Unauthorized): # { # "success": false, # "error": "Invalid signature" # } # Error Response - Expired Request (401 Unauthorized): # { # "success": false, # "error": "Request timestamp expired" # } # Error Response - Source Fetch Failed (502 Bad Gateway): # { # "success": false, # "error": "Source fetch failed: 404" # } ``` -------------------------------- ### Configure Wrangler TOML for R2 Bucket Source: https://github.com/api-grip/storage-transfer-worker/blob/main/README.md Configuration snippet for `wrangler.toml` to link a Cloudflare Worker to an R2 bucket. It specifies the worker's main file, compatibility date, and R2 bucket binding. ```toml name = "storage-transfer" main = "src/index.ts" compatibility_date = "2024-01-01" [[r2_buckets]] binding = "BUCKET" bucket_name = "your-bucket-name" ``` -------------------------------- ### Create R2 Bucket with Wrangler Source: https://github.com/api-grip/storage-transfer-worker/blob/main/README.md Command to create a new R2 bucket using the Wrangler CLI. This is a prerequisite for configuring the storage transfer worker. ```bash wrangler r2 bucket create your-bucket-name ``` -------------------------------- ### POST /api-grip/storage-transfer-worker Source: https://github.com/api-grip/storage-transfer-worker/blob/main/README.md Transfers a file from a given source URL to R2 storage. The request must be signed with an Ed25519 private key, and the signature is verified using a public key configured in the worker. ```APIDOC ## POST /api-grip/storage-transfer-worker ### Description Transfers a file from a given source URL to R2 storage. The request must be signed with an Ed25519 private key, and the signature is verified using a public key configured in the worker. Supports streaming uploads without memory buffering and includes timestamp-based replay protection. ### Method POST ### Endpoint `https://your-worker.workers.dev` (Replace with your deployed worker URL) ### Parameters #### Headers - **X-Signature** (string) - Required - The Ed25519 signature of the request body, Base64 encoded. - **Content-Type** (string) - Required - Should be `application/json`. #### Request Body - **sourceUrl** (string) - Required - The URL of the file to transfer. - **timestamp** (integer) - Required - The Unix timestamp (in milliseconds) of when the request was created. Used for replay protection. ### Request Example ```json { "sourceUrl": "https://example.com/video.mp4", "timestamp": 1234567890123 } ``` ### Response #### Success Response (200) - **success** (boolean) - Indicates if the transfer was successful. - **url** (string) - The URL where the transferred file can be accessed. - **size** (integer) - The size of the transferred file in bytes. - **contentType** (string) - The detected content type of the file. #### Response Example ```json { "success": true, "url": "https://cdn.example.com/path/to/file.mp4", "size": 1234567, "contentType": "video/mp4" } ``` #### Error Response (e.g., 400, 401, 500) - **success** (boolean) - Indicates if the operation failed. - **error** (string) - A message describing the error. #### Error Response Example ```json { "success": false, "error": "Invalid signature / Expired request" } ``` ### Error Codes - **400**: Invalid JSON / Missing fields - **401**: Invalid signature / Expired request - **405**: Method not allowed - **500**: Internal server error - **502**: Source fetch failed ``` -------------------------------- ### TypeScript Interfaces for File Transfer Request and Response Source: https://context7.com/api-grip/storage-transfer-worker/llms.txt Defines the TypeScript interfaces for the file transfer request payload and response types. The `TransferRequest` interface includes `sourceUrl`, `timestamp`, and `audience` for secure transfer initiation. The `TransferResponse` type is a union of `SuccessResponse` and `ErrorResponse` for type-safe handling of results. ```typescript import type { TransferRequest, TransferResponse, SuccessResponse, ErrorResponse } from 'apigrip-storage-transfer'; // Request payload structure const request: TransferRequest = { sourceUrl: "https://example.com/image.png", // URL to fetch and store timestamp: Date.now(), // Current time in milliseconds audience: "storage-transfer.workers.dev" // Target worker hostname }; // Response types for type-safe handling function handleResponse(response: TransferResponse) { if (response.success) { // TypeScript narrows to SuccessResponse console.log(`File stored at: ${response.url}`); console.log(`Size: ${response.size} bytes`); console.log(`Content-Type: ${response.contentType}`); } else { // TypeScript narrows to ErrorResponse console.error(`Transfer failed: ${response.error}`); } } ``` -------------------------------- ### POST / - Transfer File to R2 Storage Source: https://context7.com/api-grip/storage-transfer-worker/llms.txt Transfers a file from a source URL to R2 storage. Requires an Ed25519 signature in the `X-Signature` header for authentication. The request body includes the source URL, timestamp, and audience for signature binding. ```APIDOC ## POST / ### Description Transfers a file from a source URL to R2 storage. The request must include a valid Ed25519 signature in the `X-Signature` header, signed by the platform's private key. The request body contains the source URL, timestamp, and audience (worker hostname) for signature binding. ### Method POST ### Endpoint / ### Parameters #### Query Parameters None #### Request Body - **sourceUrl** (string) - Required - The URL of the file to fetch and store. - **timestamp** (number) - Required - The current time in milliseconds, used for replay attack protection (must be within 5 minutes of server time). - **audience** (string) - Required - The target worker hostname, used for audience binding. ### Request Example ```json { "sourceUrl": "https://example.com/assets/video.mp4", "timestamp": 1704067200000, "audience": "storage-transfer.your-domain.workers.dev" } ``` ### Response #### Success Response (200) - **success** (boolean) - Indicates if the transfer was successful. - **url** (string) - The public CDN URL of the transferred file. - **size** (number) - The size of the transferred file in bytes. - **contentType** (string) - The detected content type of the file. #### Error Response (401 Unauthorized) - **success** (boolean) - Indicates if the transfer was successful (will be false). - **error** (string) - Description of the error (e.g., "Invalid signature", "Request timestamp expired"). #### Error Response (502 Bad Gateway) - **success** (boolean) - Indicates if the transfer was successful (will be false). - **error** (string) - Description of the error (e.g., "Source fetch failed: 404"). #### Response Example (Success) ```json { "success": true, "url": "https://cdn.example.com/assets/video.mp4", "size": 15728640, "contentType": "video/mp4" } ``` #### Response Example (Error) ```json { "success": false, "error": "Invalid signature" } ``` ``` -------------------------------- ### TypeScript Types Source: https://context7.com/api-grip/storage-transfer-worker/llms.txt Defines the structure of the transfer request payload and response types for type-safe handling in TypeScript applications. ```APIDOC ## TypeScript Types ### Description Defines the structure of the transfer request payload and response types for type-safe handling in TypeScript applications. ### TransferRequest Interface ```typescript interface TransferRequest { sourceUrl: string; timestamp: number; audience: string; } ``` ### TransferResponse Interface ```typescript interface TransferResponse { success: boolean; url?: string; size?: number; contentType?: string; error?: string; } ``` ### Usage Example ```typescript import type { TransferRequest, TransferResponse } from 'apigrip-storage-transfer'; const request: TransferRequest = { sourceUrl: "https://example.com/image.png", timestamp: Date.now(), audience: "storage-transfer.workers.dev" }; async function sendTransferRequest(request: TransferRequest): Promise { // ... implementation to send request and receive response ... return {} as TransferResponse; // Placeholder } async function handleFileTransfer() { const response = await sendTransferRequest(request); if (response.success) { console.log(`File stored at: ${response.url}`); console.log(`Size: ${response.size} bytes`); console.log(`Content-Type: ${response.contentType}`); } else { console.error(`Transfer failed: ${response.error}`); } } ``` ``` -------------------------------- ### Success Response from Storage Transfer Worker Source: https://github.com/api-grip/storage-transfer-worker/blob/main/README.md JSON structure representing a successful file transfer response from the worker. It includes a success flag, the URL of the transferred file, its size, and content type. ```json { "success": true, "url": "https://cdn.example.com/path/to/file.mp4", "size": 1234567, "contentType": "video/mp4" } ``` -------------------------------- ### Error Response from Storage Transfer Worker Source: https://github.com/api-grip/storage-transfer-worker/blob/main/README.md JSON structure representing an error response from the worker. It includes a success flag set to false and an error message detailing the issue. ```json { "success": false, "error": "Error message" } ``` -------------------------------- ### Ed25519 Signature Verification in TypeScript Source: https://context7.com/api-grip/storage-transfer-worker/llms.txt Verifies the authenticity of incoming requests using Ed25519 signatures. It extracts the signature from the 'X-Signature' header, retrieves the raw request body, and uses the platform's public key to validate the signature against the body. This process ensures that requests are legitimate and have not been tampered with. ```typescript // Internal signature verification flow (for understanding) // The worker performs this automatically on each request // 1. Extract signature from header const signature = request.headers.get('X-Signature'); // Example: "kHv2qPl8X9mN3bY5rT7wZ1aL4kM6jH8vC2nB9xQ0pRfGdE3sW5yU7iO1aS4dF6gH8jK0lZ2xC4vB6nM8qW3eAg==" // 2. Get raw request body (exact bytes that were signed) const rawBody = await request.text(); // Example: '{"sourceUrl":"https://example.com/file.mp4","timestamp":1704067200000,"audience":"worker.dev"}' // 3. Verify signature using platform public key const publicKeyBytes = base64ToArrayBuffer(env.PLATFORM_PUBLIC_KEY); const signatureBytes = base64ToArrayBuffer(signature); const messageBytes = new TextEncoder().encode(rawBody); const publicKey = await crypto.subtle.importKey( 'raw', publicKeyBytes, { name: 'Ed25519' }, false, ['verify'] ); const isValid = await crypto.subtle.verify('Ed25519', publicKey, signatureBytes, messageBytes); // Returns true if signature is valid, false otherwise ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.