feed.go 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. package main
  2. import (
  3. "cmp"
  4. "encoding/xml"
  5. "net/http"
  6. "time"
  7. )
  8. const feedItems = 20
  9. type rss struct {
  10. XMLName xml.Name `xml:"rss"`
  11. Version string `xml:"version,attr"`
  12. DC string `xml:"xmlns:dc,attr"` // Dublin Core, for dc:creator
  13. Channel rssChannel `xml:"channel"`
  14. }
  15. type rssChannel struct {
  16. Title string `xml:"title"`
  17. Link string `xml:"link"`
  18. Description string `xml:"description"`
  19. LastBuildDate string `xml:"lastBuildDate,omitempty"`
  20. Items []rssItem `xml:"item"`
  21. }
  22. type rssItem struct {
  23. Title string `xml:"title"`
  24. Link string `xml:"link"`
  25. GUID string `xml:"guid"`
  26. PubDate string `xml:"pubDate"`
  27. Description string `xml:"description,omitempty"`
  28. // RSS's own <author> must be an email address; dc:creator takes a name.
  29. Creator string `xml:"dc:creator"`
  30. }
  31. func (a *app) feed(w http.ResponseWriter, r *http.Request) {
  32. idx, err := a.store.Index()
  33. if err != nil {
  34. a.serverError(w, err)
  35. return
  36. }
  37. ch := rssChannel{
  38. Title: a.siteName,
  39. Link: a.siteURL + "/",
  40. Description: "Posts from " + a.siteName,
  41. }
  42. defaultAuthor := a.config.Get().DefaultAuthor
  43. for i, p := range idx.posts {
  44. if i == feedItems {
  45. break
  46. }
  47. if i == 0 {
  48. ch.LastBuildDate = p.Date.Format(time.RFC1123Z)
  49. }
  50. link := a.siteURL + "/posts/" + p.Slug
  51. ch.Items = append(ch.Items, rssItem{
  52. Title: p.Title,
  53. Link: link,
  54. GUID: link,
  55. PubDate: p.Date.Format(time.RFC1123Z),
  56. Description: p.Summary,
  57. Creator: cmp.Or(p.Author, defaultAuthor),
  58. })
  59. }
  60. out, err := xml.MarshalIndent(rss{Version: "2.0", DC: "http://purl.org/dc/elements/1.1/", Channel: ch}, "", " ")
  61. if err != nil {
  62. a.serverError(w, err)
  63. return
  64. }
  65. w.Header().Set("Content-Type", "application/rss+xml; charset=utf-8")
  66. w.Write([]byte(xml.Header))
  67. w.Write(out)
  68. }