Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save davelevine/229d3fc8d9c75d99c35950e564dbb907 to your computer and use it in GitHub Desktop.
Save davelevine/229d3fc8d9c75d99c35950e564dbb907 to your computer and use it in GitHub Desktop.
Rewrite Subdomain URL for B2 with Cloudflare CDN

Remove B2 /file/<bucket-name> Prefix

While the article from James Ross is solid and works very well with images, I found it fell short with any streaming video with the Bandwidth Alliance (to be fair, the article mentions nothing about videos, only images). Although the URL was being rewritten, it didn't seem to be handling video properly and even short videos were taking a long time to load.

That being said, the following seems to work perfectly...

Note: None of this code is mine. I'm basically standing on the shoulders of giants.

/**
 * When requesting a file, adds the URL bits necessary in the background to get
 * it from a public B2 bucket.
 *
 * Also modifies requests for .boot, .cfg, and .pub to return the Content-Type
 * of `text/plain` (instead of the usual `application/octet-stream` or
 * `application/x-mspublisher`) that B2 would set for you automatically.
 *
 * For example:
 * You have a proxied CNAME `i.example.com` on CloudFlare pointing
 * to `f001.backblazeb2.com`.
 * To access `/test.txt` in the root of the bucket called `example-bucket`, the
 * URL would normally be `https://i.example.com/file/example-bucket/test.txt`
 * Installing this worker makes it so that the URL becomes simply
 * `https://i.example.com/test.txt`.
 */
async function handleRequest(request) {
    let url = new URL(request.url)
    // make sure you set B2_BUCKET_NAME as an environment variable
    url.pathname = `/file/${B2_BUCKET_NAME}${url.pathname}`
    let modified = new Request(url.toString(), request)
    let response = await fetch(modified, {
        cf: { cacheTtl: parseInt(CF_CACHE_TTL) }
    })
    let respURL = new URL(response.url)

    // customize Content-Type headers for various extensions here if you like
    if (/\.(pub|boot|cfg)$/.test(respURL.pathname)) {
        response = new Response(response.body, response)
        response.headers.set('Content-Type', 'text/plain')
    }
    return response
}

addEventListener('fetch', event => {
    event.respondWith(handleRequest(event.request))
})
  • Log into Cloudflare.
  • Open Workers.
  • Create a new Worker.
  • Remove the template script and add the above script.
  • Give the Worker a name and deploy the Worker.
  • Open the Settings for the Worker script and enter the following:
Variable name Value
B2_BUCKET_NAME <bucket-name>
CF_CACHE_TTL 86400
  • Open your site in Cloudflare and navigate to the Workers tab.
  • Add a new route.
  • Set the route to <subdomain>.your-domain.com/* and select the Worker you previously created.

One Step Further

I wrote a separate Gist on how to properly cache content hosted on B2 with Cloudflare. It can be found here.

Credit where it's due

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment