DEV Community

Cover image for Serverless maintenance page w/ Cloudflare
Oleg Khalin
Oleg Khalin

Posted on

Serverless maintenance page w/ Cloudflare

History

A few weeks ago I realized that missed list from the hosting provider about the planned network equipment update and got connection timeout on production servers. Hopefully, downtime was less than 15 minutes and business wasn't impacted, but our client must know what's going on and we need a maintenance screen, which will not depend on our servers. After this accident, I start thinking about how to resolve it. Few days after i realized that i can pass traffic using Cloudflare Worker's routes even before it pass target servers.

Requirements

  • Website proxied using Cloudflare
  • Cloudflare Free plan
  • Maintenance page HTML

Project setup

Init basic npm project

mkdir maintenance && cd maintenance && npm init
Enter fullscreen mode Exit fullscreen mode

Init wrangler project

npx wrangler init
Enter fullscreen mode Exit fullscreen mode

Select fetch handler in init script

Let's test it
After adding scripts to packages.json

"workers:dev": "wrangler dev",
"workers:deploy": "wrangler publish",    
Enter fullscreen mode Exit fullscreen mode

After these changes run

npm run workers:dev
Enter fullscreen mode Exit fullscreen mode

Result:
Image description

Okay, now we have our worker handler, next steps are to create our index.html and its assets.

Create index.html

mkdir public && touch public/index.html
Enter fullscreen mode Exit fullscreen mode

Add site attribute to wrangler.toml

site = { bucket = "./public" }
Enter fullscreen mode Exit fullscreen mode

let's update our worker code

Install KV package

npm install -D @cloudflare/kv-asset-handler
Enter fullscreen mode Exit fullscreen mode

Import kv-asset-handler and add assetManifest

import {getAssetFromKV} from "@cloudflare/kv-asset-handler";
// @ts-ignore defined by workers
import manifestJSON from '__STATIC_CONTENT_MANIFEST'

const assetManifest = JSON.parse(manifestJSON)
Enter fullscreen mode Exit fullscreen mode

Update Env interface

export interface Env {
    __STATIC_CONTENT: KVNamespace;
}
Enter fullscreen mode Exit fullscreen mode

Fetch handler code

This code will be executed for any matched route

const { pathname } = new URL(request.url);

try { 
    const page = await getAssetFromKV(
        {
            request,
            waitUntil(promise) {
                return ctx.waitUntil(promise)
            },
        },
        {
            mapRequestToAsset: req => new Request(`${new URL(req.url).origin}/index.html`, req),
            ASSET_NAMESPACE: env.__STATIC_CONTENT,
            ASSET_MANIFEST: assetManifest
        },
    )

    return new Response(page.body, {status: 503})
} catch (e) {
    return new Response("Something went wrong", {
        status: 500
    })
}
Enter fullscreen mode Exit fullscreen mode

Let's test it again

npm run workers:dev
Enter fullscreen mode Exit fullscreen mode

public/index.html:

index.html source code

Result:

index.html in browser

Let's try to deploy it

npm run workers:deploy
Enter fullscreen mode Exit fullscreen mode

Wrangler on the first run will ask you to authorize your requests using the OAuth screen.

How to enable maintenance mode on your website?

Simple as console.log!

  1. Log in to your Cloudflare Console and Navigate to the Workers page
  2. Click on your worker Worker card
  3. Go to Triggers -> Routes -> Add route > You need to create 2 routes for common maintenance behavior.
  • domain.dev - your root page
  • domain.dev/* - wildcard for all your URIs
  1. Done! In a few seconds, all traffic will be forwarded to your Cloudflare Worker.

Final

You can check full version of page with integrated TailwindCSS included on my github. (Feel free to check this in template repository)

Thanks for reading, it's my first post. I will appreciate your feedback and advises!

Resources

Example
Github Template Repository

Screenshot

Maintenance page example

Top comments (0)