Rails' stale? method for sitemap always returns HTTP 200
-
09-09-2019 - |
Question
My Ruby on Rails application uses the following controller code to generate a sitemap.xml file:
class SitemapController < ApplicationController
layout nil
def index
headers['Content-Type'] = 'application/xml'
last_post = Post.last
if stale?(:etag => last_post, :last_modified => last_post.updated_at.utc)
respond_to do |format|
format.xml { @posts = Post.sitemap } # sitemap is a named scope
end
end
end
end
My understanding is that the stale?
method should ensure a HTTP 304 Not Modified response if the content hasn't changed. However, whenever I test this using curl or a web browser I always get an HTTP 200:
$ curl --head localhost:3000/sitemap.xml HTTP/1.1 200 OK Connection: close Date: Mon, 13 Apr 2009 15:50:00 GMT Last-Modified: Wed, 08 Apr 2009 16:52:07 GMT X-Runtime: 100 ETag: "5ff2ed60ddcdecf291e7191e1ad540f6" Cache-Control: private, max-age=0, must-revalidate Content-Type: application/xml; charset=utf-8 Content-Length: 29318
Am I using the stale?
method correctly? Is it even possible to test this locally?
Solution
it is likely that your Rails code is just fine but curl is not sending the If-Modified-Since header when you perform your test. From the curl docs:
TIME CONDITIONS
HTTP allows a client to specify a time condition for the document it requests. It is If-Modified-Since or If-Unmodified-Since. Curl allow you to specify them with the -z/--time-cond flag.
For example, you can easily make a download that only gets performed if the remote file is newer than a local copy. It would be made like:
curl -z local.html http://remote.server.com/remote.html
Or you can download a file only if the local file is newer than the remote one. Do this by prepending the date string with a '-', as in:
curl -z -local.html http://remote.server.com/remote.html
You can specify a "free text" date as condition. Tell curl to only download the file if it was updated since yesterday:
curl -z yesterday http://remote.server.com/remote.html
Curl will then accept a wide range of date formats. You always make the date check the other way around by prepending it with a dash '-'.