Sinatra, Rack::Test, and Conditional GET requests

2020-05-29 05:07发布

I've got a Sinatra 1.2.0 app that is doing Last-Modified validation caching with Rack::Cache. Things are working great-- I call last_modified in my route body and if the cache has an up-to-date copy, the rest of the execution halts, my app responds to the cache with 304 Not Modified, and the cache serves the cached page without having to generate a new one.

My issue is in trying to write tests for this process. Using Rack::Test and Minitest::Spec, I'm simulating the cache's conditional Get request like so:

  header "If-Modified-Since", (Time.now.midnight + 1.hour).httpdate
  get "/test-url" 
  last_response.status.must_equal 304

However, that assertion on the last line fails. The app is still sending a 200 status message. Could I be setting up the request wrong? Does Rack::Test do conditional GET's correctly? Any advice would be appreciated.

2条回答
beautiful°
2楼-- · 2020-05-29 05:49

I was having a similar problem with the If-None-Match header and ETags. I couldn't get this working either with Rack::Test's header method. But what worked was this:

get '/test-url', {}, {"HTTP_IF_NONE_MATCH" => '"15-xyz"'}
last_response.status.should == 304

So, in your case, try:

get '/test-url', {}, {"HTTP_IF_MODIFIED_SINCE" => (Time.now.midnight + 1.hour).httpdate}
last_response.status.must_equal 304

Credits: This was inspired by how Rack::Test implements follow_redirect!

查看更多
够拽才男人
3楼-- · 2020-05-29 05:49

I would use the header that is sent from the response, that is what the actual HTTP client should be using to generate the next request:

# first time responds with the content
get "/test-url" 
last_response.status.must_equal 200 

# but includes a header timestamp to be used by the client
last_modified = last_response.headers["Last-Modified"] 
last_modified.wont_be_nil

# next time, it just responds with a 304 Not Modified status
get "/test-url", {}, {"HTTP_IF_MODIFIED_SINCE" => last_modified}
last_response.status.must_equal 304
查看更多
登录 后发表回答