I like to style my web feeds. Until recently, I thought that Safari simply didn’t support this, because when I tried it, it would just ask if I wanted to load the page in my feed reader.
This is ok, if you have one installed, but I’m not even sure what happened to users that didn’t already have a feed reader installed. I’d prefer the browser to display the styled feed and let the user copy the URL into their reader.
It turns out this has been possible all along!
The punchline:
Serve your RSS feed with the X-Content-Type-Options: nosniff
HTTP header set.
My feeds are now viewable directly in any browser:
Discovery
I read a Mastodon post praising the lovely Standard Ebooks site, including a shout-out to its nicely styled feeds.
There’s OPDS (the catalog feed format), and RSS and Atom. Normally, you make the mistake of going to a feed URL in your browser instead of a specific program to read feeds, and you’re punished with horrible XML. But click on any feed link here and it’s the nice looking HTML like the rest of the site.
I happened to be on iOS at the time (which constrains me to Safari only), and when I clicked through to the various feed pages, it was true: it showed me a nicely laid out feed. Examining the feed source showed a normal-looking RSS feed, and the W3C feed validator indicates it’s a fully valid feed. What are they doing that I wasn’t?
Coincidentally, Matt Webb had recently posted his colophon, and Simon Wilison linked to it noting Matt’s styled RSS feed. I read Simon’s post on my phone as well, and tried the link, and it too worked great in Safari.
I thought about it for a minute and wondered if there was a header that controlled this.
See `curl -I` output comparing the sites
Standard Ebooks
> curl -I https://standardebooks.org/feeds/rss/new-releases
HTTP/2 200
strict-transport-security: max-age=15768000
x-frame-options: sameorigin
x-content-type-options: nosniff
x-xss-protection: 1; mode=block
referrer-policy: no-referrer-when-downgrade
content-security-policy: default-src 'self';
cache-control: no-store
last-modified: Wed, 13 Nov 2024 02:31:06 GMT
etag: "1c042e-3bdf-6269c0b6a2088"
content-length: 15327
content-type: application/rss+xml
date: Thu, 14 Nov 2024 03:40:45 GMT
server: Apache
Matt Webb
> curl -I https://interconnected.org/home/feed
HTTP/1.1 200 OK
Date: Thu, 14 Nov 2024 01:26:20 GMT
Server: Apache/2.4.41 (Ubuntu)
Content-Length: 64882
x-content-type-options: nosniff
Vary: Accept-Encoding
Content-Type: application/xml; charset=utf-8
My blog
> curl -I https://me.micahrl.com/blog/rss.xml
HTTP/2 200
accept-ranges: bytes
age: 0
cache-control: public,max-age=0,must-revalidate
cache-status: "Netlify Edge"; fwd=miss
content-type: application/xml
date: Thu, 14 Nov 2024 03:40:53 GMT
etag: "b5caa51975a8b10766bd5c3e8ca49c50-ssl"
onion-location: http://mgv3s6mkbisnggxz5xg3f75vkch67qmj5fkw5yaaazztaqofmgplddad.onion/
server: Netlify
strict-transport-security: max-age=31536000
x-nf-request-id: 01JCMC4Y2TNJSEW5EZ2RSW4J03
x-underappreciated-truth: "Having a defensible opinion takes work."
content-length: 2209662
The Content-Type
header stood out to me as different;
content-type: application/xml
: minecontent-type: application/rss+xml
: Standard EbooksContent-Type: application/xml; charset=utf-8
: Matt Webb
But changing mine to match either of theirs didn’t make a difference to Safari.
I examined the list more closely and the thing that both of their sites had that mine didn’t was
X-Content-Type-Options: nosniff
.
This turned out to be the missing piece!
My content-type: application/xml
works fine when accompanied by the nosniff header,
though I did change it to the more specific Content-Type: application/xml; charset=utf-8
.
Existing documentation
When writing my RSS styles blog post,
I recall reading somewhere that all browsers don’t support it.
However, it has been
documented
in Matt Webb’s pretty-feed-v3.xsl
since at least 2021.
I had seen that XSL stylesheet before, but hadn’t read it closely. I took another look via a link from Keith Wagner’s blog post on feed styles, which I only found by searching for articles about RSS and nosniff.