Turning a Git Repository into a Simple File Host with Cloudflare Workers

Posted on:

(post originally hosted elsewhere)

Recently I used CloudFlare Workers for the first time to create the website you're reading right now (look at Fruition to learn how I did it), and I decided to try out writing some of my own workers to get an idea of what it could do.

I was in need of a simple static file host to serve various small files - stuff like HTML, presentations, PDFs etc - and thought about how Git repository hosts generally allow you to view a file within a repository in its raw format, served directly to you without modifications. I figured that I could use a CloudFlare Worker to proxy a request to a raw file path on my Git hosting service, and rewrite any necessary headers to ensure that files are served to browsers correctly.

Here's how I did it:

  1. If you do not already have an account, sign up at CloudFlare and follow the step-by-step instructions provided to set up your domain to use their services.
  2. Click the workers button at the top of the page
  3. Set up your worker subdomain - this can be anything you like (if prompted), then click the manage workers button
  4. Click the create worker button
  5. In the script editor on the left half of the page, replace the example script with this:
addEventListener('fetch', event => {
    event.respondWith(handleRequest(event.request))
})

// add a link to the raw file content host pointed at your primary ref
const REPO_URL = 'https://raw.githubusercontent.com/exampleuser/examplerepo/main/'

const PATH_REGEX = /(?<=/*YOUR DOMAIN HERE*/\/).+/

const mimeTable = {
    'html': 'text/html',
    'css': 'text/css',
    'jpeg': 'image/jpeg',
    'jpg': 'image/jpeg',
    'js': 'text/javascript',
    'json': 'application/json',
    'png': 'image/png',
    'txt': 'text/plain'
}

/**
* Respond to the request
* @param {Request} request
*/
async function handleRequest(request) {
    const req = new Request(request);

    const path = req.url.match(PATH_REGEX)[0];
    const extension = path.split('.').pop();

    const file = await fetch(REPO_URL + path);
    if (!file.ok) return new Response(null, {status: file.status});

    const response = new Response(file.body, file);

    const contentDisposition = response.headers.get('content-disposition');
    if (contentDisposition) response.headers.delete('content-disposition');

    response.headers.set('content-type', mimeTable[extension]);
    return response;
}
  1. Click the save and deploy button, and confirm that you want to save and deploy
  2. Go back to your domain's dashboard, and click the workers button again like in step 2
  3. Click the add route button
  4. Specify the route that the worker function will serve git repository assets for (e.g. files.exampledomain.com/*), select your worker function that you just created in the worker dropdown and then click save
  5. Click the DNS button at the top of the page
  6. Add a CNAME record, with the name set to the domain used in the worker route, and the target can be set to a non-existent record (e.g. sinkhole.exampledomain.com)
  7. Try and open a file in your git repository by visiting https://<WORKER_ROUTE_DOMAIN>/<FILENAME>.<EXT>

Your Git repository is now like a simple file hosting server - files can be loaded directly over HTTP now. Since the worker script removes the content-disposition header if it is present and corrects the content-type header, it can also be used as an asset source within HTML and CSS.


Tagged with:

More posts: