views:

402

answers:

1

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?

+2  A: 

Hi John, 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 '-'.

Adam Alexander
Thanks Adam, that was it.
John Topley
That's great, I was hoping it would be helpful to you. Thanks for the update!
Adam Alexander