My Blog now supports RSS
Tags: rss, coding, beginners, go
Published: 2024-02-08 19:57:31

---
title: My Blog now supports RSS
published: true
date: 2024-02-01 22:10:00 UTC
tags: rss,coding,beginners,golang
canonical_url: https://www.ersin.nz/articles/rss-in-2024
---

Behold, the latest and greatest feature on my tiny blog platform.  [RSS feeds](/feed.xml)! 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:

```html
<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:

```xml
<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&#x27;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](https://xml-to-go.github.io/). 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.
```golang
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

```golang
    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.

```golang
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!