Behold, the latest and greatest feature on my tiny blog platform. RSS feeds! Yes reader, we now support the uber trending web 2.0 tech from 2005.
Now, is it relevant to have rss in 2024? I'm not sure the answer to that, and I'm not going to spend time on it today. Stay tuned if you want to get straight in to the nitty gritty details of how to add a rss feed to any site built using golang.
What is RSS?
RSS is a way to subscribe to a website, and get updates when new content is published. It's a simple format, and a simple protocol. The protocol is based on http, and exposes itself via a url with an XML format.
How to tell the web about your RSS feed
The first step is to tell the world about your RSS feed. This is done by adding a link tag to the head of your html page. This is a simple html tag that looks like this:
<link rel="alternate" type="application/rss+xml" title="RSS Feed" href="/rss.xml" />
How to generate the RSS feed
Here's what we are trying to generate, a simple XML document that looks like the following:
<rss version="2.0">
<channel>
<title>Hacker News</title>
<link>https://news.ycombinator.com/</link>
<description>Links for the intellectually curious, ranked by readers.</description>
<item>
<title>Making a PDF that's larger than Germany</title>
<link>https://alexwlchan.net/2024/big-pdf/</link>
<pubDate>Wed, 31 Jan 2024 22:47:47 +0000</pubDate>
<comments>https://news.ycombinator.com/item?id=39210507</comments>
<description><![CDATA[<a href="https://news.ycombinator.com/item?id=39210507">Comments</a>]]></description>
</item>
The key parts that should be standing out are title
, link
, description
and pubDate
. These are what we will use to build up our own feed.
Building all that XML by hand is a pain, so we are going to do this the easy way. Behold xml -> golang generation. This online tool is
the easy way to build up your type structs, simply grab that whole document and paste it in to the tool. It will generate the golang structs for you automagically.
The generator will split out a big nested type. The code will contain all the necessary annotations and incantations to make your rss feed, we simply need to fill in the blanks with our own feeds parameters.
rs := Rss {
//... a whole bunch of fields here
}
err := xml.NewEncoder(w).Encode(rs)
Actual encoding can then be done using the familiar and easy to use Encoder
interface.
A gotcha with dates
There is one catch with the generated type, it expects the pubDate
to be a string, we need to serialize a date string for this field. This is all well and fine, you probably assume that a good all ISO8601 date will work.
You would be wrong to think this. It's closer to RFC822
. So you might think the built in RFC822 formatter from Go's great standard library. Well, almost, but not quite! The RSS feed is particularly janky, and requires us to use a 4 digit year.
To save you a bunch of time just use
"02 Jan 2006 15:04 MST"
. Oh, and make sure to include the timezone it was posted in. This is a requirement of the RSS spec. Check out the below example
gmtTimeLoc := time.FixedZone("GMT", 0)
for _, param := range fp.Posts {
itm = append(itm, Item{
Title: param.Title,
Link: "https://" + param.URL,
Description: param.Description,
PubDate: param.PubDate.In(gmtTimeLoc).Format("02 Jan 2006 15:04 MST"),
GUID: struct {
Text string `xml:",chardata"`
IsPermaLink string `xml:"isPermaLink,attr"`
}{
Text: "https://" + param.URL,
IsPermaLink: "true",
},
})
}
The above is an example of how I mush my regular Post
type into the rss type. As you can see I'm making the date field be in the gmtTimeLocation, and using the expected time format string.
How to make the rss endpoint
The final step is to make the endpoint that will serve the rss feed. This is a simple http.Handler
that will serve the rss feed.
func rssHandler(w http.ResponseWriter, r *http.Request) {
//... generate the rss feed, posts, fill out the Rss type.
w.Header().Set("Content-Type", "application/rss+xml") // always include this
w.WriteHeader(200) // always include this
//... write the rss feed to the response
err := xml.NewEncoder(w).Encode(rs)
if err != nil {
http.Error(w, err.Error(), 500)
}
}
As you can see, it's all straight forward and familiar. That's one of the gorgeous things about RSS feeds and the go language. Simple, easy to understand and easy to implement. A great evening project to make your blog just a tiny bit more awesome.
The important part in the above example is to have a Content-Type
header. After all this
Wrapping up
The RSS feed is a cool little evening project I implemented to make this tiny blog platform more awesome. Golang as a language makes it easy to do all this with just the standard library. There's a few gotcha's but nothing too crazy. I hope you enjoyed this little write up, and I hope you enjoy the RSS feed. If you're reading this from a RSS feed, cool! Didn't know people actually still used these things!
Top comments (0)