{"id":46362,"date":"2025-01-08T14:24:33","date_gmt":"2025-01-08T19:24:33","guid":{"rendered":"https:\/\/mjtsai.com\/blog\/?p=46362"},"modified":"2025-01-08T14:31:08","modified_gmt":"2025-01-08T19:31:08","slug":"rss-cache-control","status":"publish","type":"post","link":"https:\/\/mjtsai.com\/blog\/2025\/01\/08\/rss-cache-control\/","title":{"rendered":"RSS Cache Control"},"content":{"rendered":"<p>Brent Simmons reported to me that my blog&rsquo;s RSS feed wasn&rsquo;t updating in recent versions of NetNewsWire. They&rsquo;ve added support for the <code>Cache-Control<\/code> response header, and, for reasons unknown, my site was returning an interval of <em>2 days<\/em>:<\/p>\n\n<pre>\n$ curl --head https:\/\/mjtsai.com\/blog\/feed\/\nHTTP\/2 200 \ndate: Wed, 08 Jan 2025 14:28:24 GMT\nserver: Apache\nvary: Accept-Encoding,Cookie,User-Agent\nlink: &#60;https:\/\/mjtsai.com\/blog\/wp-json\/&#62;; rel=\"https:\/\/api.w.org\/\"\netag: \"9efc6f6ed8885592fcee58bc1685dcaf\"\ncache-control: max-age=172800\nexpires: Fri, 10 Jan 2025 14:28:24 GMT\ncontent-type: application\/rss+xml; charset=UTF-8\n<\/pre>\n\n<p>even though plain HTML content was only cached for 10 minutes:<\/p>\n\n<pre>\n$ curl --head https:\/\/mjtsai.com\/blog\/\nHTTP\/2 200 \ndate: Wed, 08 Jan 2025 14:34:20 GMT\nserver: Apache\nvary: Accept-Encoding,Cookie,User-Agent\ncache-control: max-age=3, must-revalidate\ncontent-length: 307509\nlast-modified: Wed, 08 Jan 2025 14:30:02 GMT\ncache-control: max-age=600\nexpires: Wed, 08 Jan 2025 14:44:20 GMT\ncontent-type: text\/html; charset=UTF-8\n<\/pre>\n\n<p>I spent a while trying to figure out why WordPress would do that, but it turns out to be <a href=\"https:\/\/help.dreamhost.com\/hc\/en-us\/articles\/216363157-Cache-a-website-with-an-htaccess-file\">a default<\/a> set by my server provider, DreamHost. RSS feeds fall under the default file type even though they are <em>more<\/em> likely to change frequently.<\/p>\n\n<p>There are various ways to override this using Apache&rsquo;s <tt>.htaccess<\/tt> file. Simmons is using this for his feed:<\/p>\n\n<pre>\n&#60;Files \"rss.xml\"&#62;\n  &#60;IfModule mod_headers.c&#62;\n      Header set Cache-Control \"max-age=300\"\n  &#60;\/IfModule&#62;\n&#60;\/Files&#62;\n<\/pre>\n\n<p>But I don&rsquo;t want to list each file separately because this blog has many feeds, e.g. one for the comments on each post. What seems to work is setting the expiration by MIME type:<\/p>\n\n<pre>\n&#60;IfModule mod_expires.c&#62;  \n  ExpiresActive on\n  ExpiresByType application\/rss+xml \"access plus 300 seconds\"\n  ExpiresByType application\/atom+xml \"access plus 300 seconds\"\n&#60;\/IfModule&#62;  \n<\/pre>\n\n<p>Please let me know if you run into any problems with this.<\/p>\n\n<p>Previously:<\/p>\n<ul>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2024\/12\/09\/netnewswire-6-1-6\/\">NetNewsWire 6.1.6<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2024\/08\/06\/netnewswire-and-conditional-get-issues\/\">NetNewsWire and Conditional GET Issues<\/a><\/li>\n<\/ul>","protected":false},"excerpt":{"rendered":"<p>Brent Simmons reported to me that my blog&rsquo;s RSS feed wasn&rsquo;t updating in recent versions of NetNewsWire. They&rsquo;ve added support for the Cache-Control response header, and, for reasons unknown, my site was returning an interval of 2 days: $ curl --head https:\/\/mjtsai.com\/blog\/feed\/ HTTP\/2 200 date: Wed, 08 Jan 2025 14:28:24 GMT server: Apache vary: Accept-Encoding,Cookie,User-Agent [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"apple_news_api_created_at":"2025-01-08T19:24:36Z","apple_news_api_id":"0db1a2e2-77b6-4542-bba3-a07c163adc6d","apple_news_api_modified_at":"2025-01-08T19:31:10Z","apple_news_api_revision":"AAAAAAAAAAAAAAAAAAAAAA==","apple_news_api_share_url":"https:\/\/apple.news\/ADbGi4ne2RUK7o6B8FjrcbQ","apple_news_coverimage":0,"apple_news_coverimage_caption":"","apple_news_is_hidden":false,"apple_news_is_paid":false,"apple_news_is_preview":false,"apple_news_is_sponsored":false,"apple_news_maturity_rating":"","apple_news_metadata":"\"\"","apple_news_pullquote":"","apple_news_pullquote_position":"","apple_news_slug":"","apple_news_sections":"\"\"","apple_news_suppress_video_url":false,"apple_news_use_image_component":false,"footnotes":""},"categories":[2],"tags":[544,1854,872,392,52,1659,96],"class_list":["post-46362","post","type-post","status-publish","format-standard","hentry","category-technology","tag-apache","tag-atom-syndication-format","tag-dreamhost","tag-netnewswire","tag-rss","tag-this-blog","tag-web"],"apple_news_notices":[],"_links":{"self":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/46362","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/comments?post=46362"}],"version-history":[{"count":2,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/46362\/revisions"}],"predecessor-version":[{"id":46366,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/46362\/revisions\/46366"}],"wp:attachment":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/media?parent=46362"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/categories?post=46362"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/tags?post=46362"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}