Reputation: 4114
I am trying to build an API using Rails that will inspect the request
header for "If-Modified-Since"
and render only the objects that were modified past that date. The problem is I am stuck trying to obtain the value from the request header in the controller.
# API
def index
@products = Product.where{updated_at > request.headers["If-Modified-Since"]}
render "v1/products/index"
end
What is the correct way for extracting values from the request header?
Upvotes: 1
Views: 5033
Reputation: 914
According to the W3 specifications, your method of using If-Modified-Since is completely valid. [1] The other responders here are incorrect in saying that it is non-standard or will corrupt your cache. It's not very RESTful and is not recommended to include state information within your data (such as GET parameters).
To answer you question, you can use stale?
to generate either a 304 (if it hasn't been modified) or generate the actual content. Here's an example:
def index
if_modified_since = request.headers['If-Modified-Since'] || DateTime.new
@items = Item.where("updated_at > ?", if_modified_since).order(updated_at: :desc)
if stale?(@items.first)
render json: @items
end
end
Note that this assumes @items always contains an item. You can tailor it to your needs if it doesn't always return something.
Upvotes: 3
Reputation: 4311
request.if_modified_since
or request.headers["HTTP_IF_MODIFIED_SINCE"]
Be aware that this is a non-standard use of the header. It generally refers to whether any content of the page has changed since the time specified in If-Modified-Since, not that the page should only include the content which has changed.
You might also be interested in the stale?
method.
Upvotes: 1
Reputation: 11510
First: If-Modified-Since
is for HTTP cache validation. Please don't use it this way. Use a parameter instead.
To answer your question: request.headers[]
is the proper way of accessing request headers. For reference, request
is an ActionDispatch::Request object.
The problem here is how you're trying to express the constraint. You're passing a block into ActiveRecord
's #where
method, and the block doesn't make any sense (Symbol#>(String)
?). You can express this as a SQL fragment, like:
Product.where("updated_at > ?", params[:last_update])
Alternately, you could drop in Squeel, and write:
Product.where{ updated_at > params[:last_update] }
Upvotes: 5