Skip to content

Instantly share code, notes, and snippets.

@HashNuke
Last active May 7, 2025 19:47
Show Gist options
  • Select an option

  • Save HashNuke/4306c2c116cc2ccda9778412bcaca80c to your computer and use it in GitHub Desktop.

Select an option

Save HashNuke/4306c2c116cc2ccda9778412bcaca80c to your computer and use it in GitHub Desktop.

Revisions

  1. HashNuke revised this gist Mar 11, 2025. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions cloudflare-r2-download-worker.js
    Original file line number Diff line number Diff line change
    @@ -6,6 +6,7 @@ import jwt from '@tsndr/cloudflare-worker-jwt'
    // { binding = "STORAGE_BUCKET", bucket_name = "your_bucket_name" }
    // ]
    //
    // Also requires download_jwt_secret in the worker env

    export default {
    async fetch(request, env, ctx) {
  2. HashNuke created this gist Mar 11, 2025.
    53 changes: 53 additions & 0 deletions cloudflare-r2-download-worker.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,53 @@
    import jwt from '@tsndr/cloudflare-worker-jwt'

    // Add following config to wrangler.toml
    //
    // r2_buckets = [
    // { binding = "STORAGE_BUCKET", bucket_name = "your_bucket_name" }
    // ]
    //

    export default {
    async fetch(request, env, ctx) {
    const url = new URL(request.url)
    const jwt_secret = env.download_jwt_secret
    const token = url.searchParams.get('token')

    // for me to test if the worker is hosted fine.
    if (url.searchParams.get('x') == "test") {
    return new Response('Hello World!');
    }

    if (!token) {
    return new Response('Unauthorized', { status: 401 })
    }

    try {
    // 1. Verify JWT
    const verifiedToken = await jwt.verify(token, jwt_secret)
    if (!verifiedToken) {
    return new Response('Invalid token', { status: 401 })
    }

    // 2. Extract file information
    const fileKey = verifiedToken.payload.fileKey

    // 3. Fetch object from R2
    let object = await env.STORAGE_BUCKET.get(fileKey)
    if (object === null) {
    return new Response('Object not found', { status: 404 })
    }

    // 4. Set Cache-Control headers
    const headers = new Headers()
    headers.set('Cache-Control', 'public, max-age=3600') // Cache for 1 hour
    headers.set('Content-Type', object.httpMetadata.contentType)

    return new Response(object.body, {
    headers: headers,
    })
    } catch (error) {
    return new Response('Error: ' + error.message, { status: 500 })
    }
    },
    }