我正在尝试使用 Rails 构建一个 API,它将检查request
标头"If-Modified-Since"
并仅呈现在该日期之后修改的对象。问题是我试图从控制器中的请求标头中获取值。
# API
def index
@products = Product.where{updated_at > request.headers["If-Modified-Since"]}
render "v1/products/index"
end
从请求标头中提取值的正确方法是什么?
我正在尝试使用 Rails 构建一个 API,它将检查request
标头"If-Modified-Since"
并仅呈现在该日期之后修改的对象。问题是我试图从控制器中的请求标头中获取值。
# API
def index
@products = Product.where{updated_at > request.headers["If-Modified-Since"]}
render "v1/products/index"
end
从请求标头中提取值的正确方法是什么?
第一:If-Modified-Since
用于 HTTP 缓存验证。请不要以这种方式使用它。请改用参数。
回答您的问题:request.headers[]
是访问请求标头的正确方法。作为参考,request
是一个ActionDispatch::Request对象。
这里的问题是您如何尝试表达约束。您将一个块传递给ActiveRecord
's#where
方法,而该块没有任何意义(Symbol#>(String)
?)。您可以将其表示为 SQL 片段,例如:
Product.where("updated_at > ?", params[:last_update])
或者,您可以放入Squeel,然后编写:
Product.where{ updated_at > params[:last_update] }
根据 W3 规范,您使用 If-Modified-Since 的方法是完全有效的。[1]这里的其他响应者说它不标准或会损坏您的缓存是不正确的。它不是很 RESTful,不建议在数据中包含状态信息(例如 GET 参数)。
要回答您的问题,您可以使用stale?
生成 304(如果尚未修改)或生成实际内容。这是一个例子:
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
请注意,这假定 @items 始终包含一个项目。如果它并不总是返回某些东西,您可以根据您的需要对其进行定制。
request.if_modified_since
或者request.headers["HTTP_IF_MODIFIED_SINCE"]
请注意,这是标头的非标准用法。一般是指在If-Modified-Since中指定的时间之后,页面的内容是否发生了变化,并不是说页面应该只包含发生变化的内容。
您可能也对该stale?
方法感兴趣。