..

Making Better Use of the `Accept` Header

Shhhhhh! This post is for RSS subscribers only. Look here for more information (and to join in on the fun).

--

A while back, I wrote about a Jekyll plugin I created that cross-compiles all of my blog posts in plaintext (you can see it for yourself, just click the txt link at the bottom of this or any other post). It was a fun experiment, and allowed me to not only create a mechanism that ensures my writing can be accessed on just about any browser imaginable now, but also gave me an opportunity to DRY up my phlog code as well.

One thing I have been wanting to do for a while, though, was make better use of some HTTP request headers—specifically the Accept header—to create a more dynamic and customizable experience (and also, eventually, easter eggs). So now, as of this past weekend, you can request my blog posts in plaintext format by passing the text/plain MIME type in the Accept header!

How did I do it?

Surprisingly, it only took a handful of lines of configuration in my Caddyfile:

@text {
    header Accept text/plain
    path_regexp html (.*)(\.html)$
}

handle @text {
    @html {
		path_regexp html (.*)(\.html)$
    }

    rewrite @html {re.html.1}

    try_files {uri}.txt {uri}.html
    file_server
}

So... what exactly is happening here?

Basically, I created a Named Matcher called @text that looks for two things:

  1. An Accept header set to text/plain
  2. A request to an HTML page

When these two things are matched, I then created a Handler to respond to matched @text requests, which does a few things before responding:

  1. First, it strips the .html suffix off of the path (for example, turning /index.html to just /index)
  2. Next, it tries to load a corresponding .txt file (/index.txt)
  3. And finally, if that file can't be found, it falls back to the originally requested .html file (/index.html again)

All things considered, it's a pretty simple solution, but here's what it looks like in action with the Accept header passed:

$ curl -v -H 'Accept: text/plain' http://flower.codes/2024/01/13/four-oh-four.html
* Trying 37.16.19.121:80...
* Connected to flower.codes (37.16.19.121) port 80 (#0)
> GET /2024/01/13/four-oh-four.html HTTP/1.1
> Host: flower.codes
> User-Agent: curl/7.82.0
> Accept: text/plain
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< accept-ranges: bytes
< content-length: 2385
< etag: "s9um4u1u9"
< last-modified: Tue, 05 Mar 2024 00:17:18 GMT
< server: Fly/e29f4368 (2024-03-04)
< date: Tue, 05 Mar 2024 13:00:21 GMT
< via: 1.1 fly.io
< fly-request-id: 01HR7B6SF7PGEK6PVDZ6SY8QP5-chi
<
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
title: Four, Oh, Four...
date: 2024-01-13 14:50:00
soundtrack: "You & Me = Forever" by Zak Vortex
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

I did it.

I finally broke down and added the _tiniest_ bit of JavaScript to
my site. I know, I'm awful, but hear me out.

I've been thinking about retro computing a lot again, especially as
it pertains to The Internet (capital "T," capital "I," baby), and
I've been wanting to add a little more personality (and maybe an
easter egg or two) to things.

One thing that I _haven't_ yet set up for myself is a kickass 404
page—or... you know... a 404 page at all. I think I designed a
simple one a million moons ago, but I never actually configured my
web server to serve it up.

But I'm nothing if not an expert procrastinator, so I finally
jumped into my Caddyfile [0], pointed all its 404 responses to my
404 page, and... was supremely disappointed.

The page I had was _boring_.

So I dug into the depths of my brainpan and remembered an old
glitch effect I used half-a-dozen years ago that felt right at home
with my preferred aesthetic. Unfortunately, this meant importing
one small JavaScript file and adding a single line of code to
activate it.

But, in the interest of keeping things tidy, it's only loaded on my
error page (alongside a fun deconstruction of a rotary phone,
courtesy of our friends at OpenAI), and is all sorts of fun to look
at.

If you're interested, feel free to head directly to /404.html [1],
or just mash your keyboard a bit to get to an actual 404 error on
the flower.codes domain.

Oh, and in case you were wondering how old browsers deal with this?
The answer is twofold: not well, and it doesn't really matter.

While the actual `404.html` page can be loaded in older browsers,
most of them ignore the `<script>` tags (except for our friend
Internet Explorer, which fails hard, but I fixed that with
conditional comments [2]), but more importantly, nearly every
historical browser shows _their own error page_ when a 404 response
is encountered; so investing any real effort into backwards
compatibility is a moot point.

---
[0]: https://caddyserver.com/docs/caddyfile
[1]: http://flower.codes/404.html
[2]: https://en.wikipedia.org/wiki/Conditional_comment
---

>> This is post 022 of #100DaysToOffload

EOF

And again, with the header removed (defaulting to text/html):

$ curl -v http://flower.codes/2024/01/13/four-oh-four.html
*   Trying 37.16.19.121:80...
* Connected to flower.codes (37.16.19.121) port 80 (#0)
> GET /2024/01/13/four-oh-four.html HTTP/1.1
> Host: flower.codes
> User-Agent: curl/7.82.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< accept-ranges: bytes
< content-length: 4959
< content-type: text/html; charset=utf-8
< etag: "s9um4u3tr"
< last-modified: Tue, 05 Mar 2024 00:17:18 GMT
< server: Fly/e29f4368 (2024-03-04)
< date: Tue, 05 Mar 2024 13:01:10 GMT
< via: 1.1 fly.io
< fly-request-id: 01HR7B88RVM1Q5ZDMR6VZP2FC3-chi
<
<!DOCTYPE html><html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><meta http-equiv="X-UA-Compatible" content="IE=Edge" /><meta name="viewport" content="width=device-width, initial-scale=1" /><meta name="monetization" content="$ilp.uphold.com/prbzZ7GL6EpU" /><meta name="description" content="I did it." /><title>Four, Oh, Four... | flower.codes</title><link rel="shortcut icon" href="data:," /><link rel="home" href="http://flower.codes" /><link type="application/atom+xml" rel="alternate" href="/feed.xml" /><style type="text/css"> <!-- body { font-family: monospace, "Courier New", Courier; line-height: 1.8; } a { text-decoration: none; } a:hover { text-decoration: underline; } hr { border-top: 1px solid #cccccc; } .i { line-height: 0; } pre { width: 100%; white-space: pre-wrap; word-wrap: break-word; } ol { list-style-type: decimal-leading-zero; } #w { width: 800px; } @media only screen and (max-width: 800px) { #w,img { width: 100%; } #w { max-width: 800px; } img { height: auto; } section .footnotes { overflow-x: scroll; } } @media (prefers-color-scheme: dark) { body { background: #222222; color: #eeeeee; } .i > img { mix-blend-mode: luminosity; } pre, blockquote { background: #111111; border: 10px solid #333333; max-width: 100%; width: auto; padding: 20px; margin: 0 auto; } hr { border-top: 2px solid #333333; } } --></style><body bgcolor="#ffffff" link='#9bbc0f' vlink='#9bbc0f' alink='#9bbc0f' text="#000000"> <br /><br /> <center><table id="w" width="800" border="0" cellpadding="20" cellspacing="0"><tr><td align="left"> <font face='Monospace, Courier New, Courier'><main> <a href="/">..</a><h1>Four, Oh, Four...</h1><article><p>I did it.<p>I finally broke down and added the <em>tiniest</em> bit of JavaScript to my site. I know, I'm awful, but hear me out.<p>I've been thinking about retro computing a lot again, especially as it pertains to The Internet (capital &quot;T,&quot; capital &quot;I,&quot; baby), and I've been wanting to add a little more personality (and maybe an easter egg or two) to things.<p>One thing that I <em>haven't</em> yet set up for myself is a kickass 404 page—or... you know... a 404 page at all. I think I designed a simple one a million moons ago, but I never actually configured my web server to serve it up.<p>But I'm nothing if not an expert procrastinator, so I finally jumped into my <a href="https://caddyserver.com/docs/caddyfile">Caddyfile</a>, pointed all its 404 responses to my 404 page, and... was supremely disappointed.<p>The page I had was <em>boring</em>.<p>So I dug into the depths of my brainpan and remembered an old glitch effect I used half-a-dozen years ago that felt right at home with my preferred aesthetic. Unfortunately, this meant importing one small JavaScript file and adding a single line of code to activate it.<p>But, in the interest of keeping things tidy, it's only loaded on my error page (alongside a fun deconstruction of a rotary phone, courtesy of our friends at OpenAI), and is all sorts of fun to look at.<p>If you're interested, feel free to head directly to <a href="/404.html">/404.html</a>, or just mash your keyboard a bit to get to an actual 404 error on the flower.codes domain.<p>Oh, and in case you were wondering how old browsers deal with this? The answer is twofold: not well, and it doesn't really matter.<p>While the actual <code>404.html</code> page can be loaded in older browsers, most of them ignore the <code>&lt;script&gt;</code> tags (except for our friend Internet Explorer, which fails hard, but I fixed that with <a href="https://en.wikipedia.org/wiki/Conditional_comment">conditional comments</a>), but more importantly, nearly every historical browser shows <em>their own error page</em> when a 404 response is encountered; so investing any real effort into backwards compatibility is a moot point.<p>--<p><i>This is post 022 of <a href="https://100daystooffload.com">#100DaysToOffload</a></i></article></main><br /><footer><hr size="1" noshade /> <font color="gray"><small><i><p align='right'> <time datetime="2024-01-13">2024.01.13</time> | <a href="http://flower.codes/2024/01/13/four-oh-four.html">flower.codes</a> | <a href="/2024/01/13/four-oh-four.txt">txt</a> | <a href="https://webring.xxiivv.com/#random">webring</a> </i></small></font></footer></font></table></center> <br /><br />

<!--
     .__________________________.
     | .___________________. |==|
     | | ................. | |  |
     | | :[ Dear Human, ]: | |  |
     | | :[     Hi.     ]: | |  |
     | | ::::::::::::::::: | |  |
     | | ::::::::::::::::: | |  |
     | | ::::::::::::::::: | |  |
     | | ::::::::::::::::: | | ,|
     | !___________________! |(c|
     !_______________________!__!
    /                            \
   /  [][][][][][][][][][][][][]  \
  /  [][][][][][][][][][][][][][]  \
 (  [][][][][____________][][][][]  )
  \ ------------------------------ /
   \______________________________/
-->

While the impact here is pretty light (yay, plaintext instead of HTML), the implications are a little more fun. One idea I have been playing around with is recording my blog posts as audio files, but I could also return posts in PDF format, Microsoft Word format, or some other random format (because why not)?

The possibilities are endless, and now I have a way to serve them up in more creative and unique ways!

--

If you like this post or one of my projects, you can buy me a coffee, or send me a note. I'd love to hear from you!

--

This is post 036 of #100DaysToOffload