I’ve recently had to shut down some old platforms. This presented an interesting challenge, as I had some requirements:

  1. No ongoing server costs/maintenance
  2. Custom error messages depending on the domain, so the solution can be applied to multiple legacy platforms
  3. Work across wildcard subdomains, which are used to identify the tenant

I already manage DNS through Cloudflare, and after investigating their Workers a little bit, I found that they provide the perfect solution.

Their free tier allows for up to 100k requests per day, which these sites would easily fall under, since they’re all legacy platforms that are no longer in use.

Head into Cloudflare, create a new Worker, give it a name, and edit the code.

Make sure to edit the case statements to match your domains, and the list of paths which should trigger the error message. Any path not in that list will get a simple 404 response.


const getShutdownPage = (errMsg) => `
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Service no longer available</title>
  <style>
    body { font-family: Arial, sans-serif; }
    .shutdown-alert { background-color: #fff; width: 80%; max-width: 560px; margin: 40px auto 10px; border: 2px solid red; border-radius: 6px; padding: 12px; }
    .shutdown-alert h1 { font-size: 18px; color: red; font-weight: bold; margin: 0 0 10px; }
    .shutdown-alert p { font-size: 16px; color: #9a9a9a; margin: 0 0 10px; }
  </style>
</head>
<body>
  <div class="container">
    <div class="shutdown-alert">
      <h1>Important notice: end of service</h1>
      ${errMsg}
    </div>
  </div>
</body>
</html>
`;

addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request));
});

async function handleRequest(request) {
  const url = new URL(request.url);
  const pathname = url.pathname;
  
  let errMsg = '';

  // Add extra cases to handle additional domains and provide a custom message for each
  // Any incoming domains that aren't in the list will see the default!
  switch(true) {
    case url.hostname.endsWith('mysite.com'):
    errMsg = `
      <p>Unfortunately, this site is no longer available.</p>
      `;
      break;
    case url.hostname.endsWith('anothersite.com'):
      errMsg = `
      <p>We're sorry but this site is no longer accessible!</p>
      `;
      break;
    default:
      errMsg = `<p>This site is no longer available.</p>`;
      break;
  }

  // Customise the list of paths that _should_ display the error message
  // Any path not in this list will return a 404 error
  let errorPaths = [
    '/',
    '/signin.php',
    '/signin/',
  ];

  if(errorPaths.indexOf(pathname) !== -1) {
    const htmlContent = getShutdownPage(errMsg);
    return new Response(htmlContent, {
      headers: { 'Content-Type': 'text/html' },
    });
  } else {
    return new Response('404 Not Found', { status: 404 });
  }
}

Once this is saved and deployed, there are two more steps to complete.

Firstly, head to Settings -> Triggers.

Under the Routes section, click to add a route. In the route field, enter *.mysite.com/*, then choose the matching domain from the list of zones.

Repeat this step for each domain.

Secondly, on the same page, click to add a custom domain, and enter *.mysite.com. This will add the appropriate DNS entries onto the domain and start provisioning an SSL certificate for the worker.

Note: you’ll need to have removed any existing DNS entries before completing this step!

After a few minutes, Cloudflare will have generated an SSL certificate and activated the custom domain. You can then test things out in the browser.

If everything is working as expected:

  • going to anysubdomainhere.mysite.com will show the error
  • going to anysubdomainhere.mysite.com/signin/ will show the error
  • going to anysubdomainhere.mysite.com/someotherurl/ will return a 404

Success!