life is a succession of choices, what is yours?

Redirecting static pages

2023-07-20
4 minutes

GitHub, my public code hosting platform of choice (I have my own Gitea server, too), has GitHub Pages, a free static file hosting platform. I use GitHub Pages for a few personal projects, where I either don't need or want to host the code myself, or I want to explicitly link the code in the repository to the published artifact (supply chain security). By default, published sites are served under <username>.github.io/<repo> (eg realorangeone.github.io/django-secret-key-generator). There's a few different projects I serve from my GitHub, all from realorangeone.github.io/<repo>. But, the base URL, realorangeone.github.io doesn't do anything, it just 404s.

If I want some content served under realorangeone.github.io, I just need to make a repository named realorangeone.github.io, and it will publish there by default. This allows people to serve a portfolio or website from the root As you may have noticed, I have a website. If you've not noticed, then welcome - you're looking right at it! It's running at theorangeone.net, a domain I own and have for almost a decade at this point. I'm never going to host anything legitimate on realorangeone.github.io, I already have a website. But it'd be nice if I could redirect people who did stumble across realorangeone.github.io to the right place.

<fun-fact>

If you were to, for some reason, visit https://realorangeone.github.io/realorangeone.github.io, GitHub will redirect you to https://realorangeone.github.io.

</fun-fact>

GitHub pages is entirely static. You give it a directory of files, and it'll serve them. There's no server-side computation, no way to even modify how the page is served like you might with a platform like Netlify. This means there's no way to perform HTTP 301/302/307/308 redirects server-side.

<tangent>

Yes, there are a lot of redirect status codes...

</tangent>

I take the SEO of my site quite seriously, and do what I can to keep a reasonable ranking, so it'd be nice if I can do all this both without affecting that, and allowing search engines to follow the redirect easily. I also hate unnecessary Javascript in pages. Sure, that hate comes from having worked on unnecessarily complicated single-page apps, but I'm sure there's a way to do this without Javascript.

#Implementation

The fact you're reading this means yes, it's absolutely possible. In fact, I'll be using the same trick almost all static site generators use when they need to output "alias" or redirect pages.

<aside>

Unless they're cool and can output an nginx config directly.

</aside>

The first step is simple - we need a tiny HTML page. In the pursuit of performance, let's make it as small and simple as possible, for now:

HTML
<!DOCTYPE html>
<html>
  <head>
    <title>Redirecting...</title>
  </head>
  <body>
    <p>Redirecting...</p>
  </body>
</html>

We show a little text, both in the title and body of the page so the user knows what's happening. When a user visits our page, it'll load in its entirety. Whilst the next page is loading (which should be pretty fast for my website), the old is still shown, so it's helpful to at least show something other thank a blank screen, and tell them what's happening.

#Redirect

Next, we need to do the redirect. In the interest of completeness, let's show the not-so-nice way of doing this, with javascript:

HTML
<script>
   window.location.assign('https://theorangeone.net');
</script>

window.location.assign is supported right back to Internet Explorer 6, so it'll work just fine everywhere.

But, as I say, this uses Javascript, which is completely unnecessary here. Instead, we can use a little-known trick: http-equiv="refresh". The HTML meta tag supports simulating HTTP headers, in this case the little-known and rarely-documented Refresh header. This header functions similar to a 3xx status code with a Location header, but allows a delay, and loads the entire page before executing. Armed with this, we can issue a redirect with 1 additional tag:

HTML
<meta http-equiv="refresh" content="0;url=https://theorangeone.net" />

Redirect to my website immediately (after 0 seconds)? Done. If I wanted to add a delay, for whatever reason, just change the 0 to something else. In this case, we want the redirect to occur as quickly as possible, so 0 works fine.

#SEO

Next, we want search engines to know about the redirect. Search engines are magical things which know everything, so they'll be able to parse the refresh without issue - but we can and should give them a helping hand. In this case, we instruct search engines that whilst they're looking at realorangeone.github.io, the actual (or "canonical" in this case) URL should be theorangeone.net.

We do this with yet another tag in the head: link rel=canonical:

HTML
<link rel="canonical" href="https://theorangeone.net" />

#The result

And now, we stitch everything together into a single file. No CSS, no JS, just good ol' fashioned HTML:

HTML
<!DOCTYPE html>
<html>
  <head>
    <title>Redirecting...</title>
    <link rel="canonical" href="https://theorangeone.net" />
    <meta charset="utf-8" />
    <meta http-equiv="refresh" content="0; url=https://theorangeone.net" />
  </head>
  <body>
    <p>Redirecting...</p>
  </body>
</html>

Similar templates can be found in Hugo, Zola and Jekyll.

#Deploying

We have a HTML file, now it's time to release it upon the world.

For ease, GitHub lets you release changes straight from a branch, which saves the extra faff of waiting for CI to build a site (which would do nothing in this case). Some repository hosts, like GitLab, require a build in CI to produce a pages side.

I suspect this functionality is a free layover from their previous gh-pages branch deployment strategy. Which was a pretty horrible hack and polluted a lot of repositories.

The above file is deployed right now to realorangeone.github.io. Visit it right now and you'll see:

Bash Session
$ curl https://realorangeone.github.io/
<!DOCTYPE html>
<html>
  <head>
    <title>Redirecting...</title>
    <link rel="canonical" href="https://theorangeone.net" />
    <meta charset="utf-8" />
    <meta http-equiv="refresh" content="0; url=https://theorangeone.net" />
  </head>
  <body>
    <p>Redirecting...</p>
  </body>
</html>

I've deployed this file on GitHub and GitLab, but the same trick will work for any hosting provider which lets you write arbitrary HTML. If you need a simple redirect, this is the best way to do it.

However, If the host supports actual HTTP status codes, you absolutely should. Not only is it more correct, it's also much faster!

Share this page

Similar content

View all →

Educating internet explorer users

2022-04-15
3 minutes

Internet Explorer was, in its prime, the most popular internet browser in the world. Originally released alongside Windows 95, its headline feature seemed to be that it was maintained by Microsoft and was automatically installed. It wasn’t until Internet Explorer 2.0 in November 1995 that feature we’re used to, like…

Vintage page sheet background

Self-hosting static websites

2021-08-05
9 minutes

Static sites, ie those which are just files on disk rather than requiring a custom application or database to run, are incredibly simple to write. You can either do it yourself from scratch with a bunch of HTML, CSS and JS files, or use a generator like Hugo or Zola.…

metal chain

Making linking to my posts easier

2021-09-19
3 minutes

For anyone who’s spoken to me, they’ll know I’m very quick to link people to posts I’ve written. That’s not in terms of pushing the things I’ve written (usually), but also being able to retrieve the links as quick as possible. I recently added search search to my website, and…