1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
|
# frozen_string_literal: true
require_relative 'helper'
require 'time'
separate_testing do
require_relative '../lib/rack/conditional_get'
require_relative '../lib/rack/lint'
require_relative '../lib/rack/mock_request'
end
describe Rack::ConditionalGet do
def conditional_get(app)
Rack::Lint.new Rack::ConditionalGet.new(app)
end
it "set a 304 status and truncate body when if-modified-since hits" do
timestamp = Time.now.httpdate
app = conditional_get(lambda { |env|
[200, { 'last-modified' => timestamp }, ['TEST']] })
response = Rack::MockRequest.new(app).
get("/", 'HTTP_IF_MODIFIED_SINCE' => timestamp)
response.status.must_equal 304
response.body.must_be :empty?
end
it "set a 304 status and truncate body when if-modified-since hits and is higher than current time" do
app = conditional_get(lambda { |env|
[200, { 'last-modified' => (Time.now - 3600).httpdate }, ['TEST']] })
response = Rack::MockRequest.new(app).
get("/", 'HTTP_IF_MODIFIED_SINCE' => Time.now.httpdate)
response.status.must_equal 304
response.body.must_be :empty?
end
it "closes bodies" do
body = Object.new
def body.each; yield 'TEST' end
closed = false
body.define_singleton_method(:close){closed = true}
app = conditional_get(lambda { |env|
[200, { 'last-modified' => (Time.now - 3600).httpdate }, body] })
response = Rack::MockRequest.new(app).
get("/", 'HTTP_IF_MODIFIED_SINCE' => Time.now.httpdate)
response.status.must_equal 304
response.body.must_be :empty?
closed.must_equal true
end
it "set a 304 status and truncate body when if-none-match hits" do
app = conditional_get(lambda { |env|
[200, { 'etag' => '1234' }, ['TEST']] })
response = Rack::MockRequest.new(app).
get("/", 'HTTP_IF_NONE_MATCH' => '1234')
response.status.must_equal 304
response.body.must_be :empty?
end
it "set a 304 status and truncate body when if-none-match hits but if-modified-since is after last-modified" do
app = conditional_get(lambda { |env|
[200, { 'last-modified' => (Time.now + 3600).httpdate, 'etag' => '1234', 'content-type' => 'text/plain' }, ['TEST']] })
response = Rack::MockRequest.new(app).
get("/", 'HTTP_IF_MODIFIED_SINCE' => Time.now.httpdate, 'HTTP_IF_NONE_MATCH' => '1234')
response.status.must_equal 304
response.body.must_be :empty?
end
it "not set a 304 status if last-modified is too short" do
app = conditional_get(lambda { |env|
[200, { 'last-modified' => '1234', 'content-type' => 'text/plain' }, ['TEST']] })
response = Rack::MockRequest.new(app).
get("/", 'HTTP_IF_MODIFIED_SINCE' => Time.now.httpdate)
response.status.must_equal 200
response.body.must_equal 'TEST'
end
it "not set a 304 status if if-modified-since hits but etag does not" do
timestamp = Time.now.httpdate
app = conditional_get(lambda { |env|
[200, { 'last-modified' => timestamp, 'etag' => '1234', 'content-type' => 'text/plain' }, ['TEST']] })
response = Rack::MockRequest.new(app).
get("/", 'HTTP_IF_MODIFIED_SINCE' => timestamp, 'HTTP_IF_NONE_MATCH' => '4321')
response.status.must_equal 200
response.body.must_equal 'TEST'
end
it "set a 304 status and truncate body when both if-none-match and if-modified-since hits" do
timestamp = Time.now.httpdate
app = conditional_get(lambda { |env|
[200, { 'last-modified' => timestamp, 'etag' => '1234' }, ['TEST']] })
response = Rack::MockRequest.new(app).
get("/", 'HTTP_IF_MODIFIED_SINCE' => timestamp, 'HTTP_IF_NONE_MATCH' => '1234')
response.status.must_equal 304
response.body.must_be :empty?
end
it "not affect non-GET/HEAD requests" do
app = conditional_get(lambda { |env|
[200, { 'etag' => '1234', 'content-type' => 'text/plain' }, ['TEST']] })
response = Rack::MockRequest.new(app).
post("/", 'HTTP_IF_NONE_MATCH' => '1234')
response.status.must_equal 200
response.body.must_equal 'TEST'
end
it "not affect non-200 requests" do
app = conditional_get(lambda { |env|
[302, { 'etag' => '1234', 'content-type' => 'text/plain' }, ['TEST']] })
response = Rack::MockRequest.new(app).
get("/", 'HTTP_IF_NONE_MATCH' => '1234')
response.status.must_equal 302
response.body.must_equal 'TEST'
end
it "not affect requests with malformed HTTP_IF_NONE_MATCH" do
bad_timestamp = Time.now.strftime('%Y-%m-%d %H:%M:%S %z')
app = conditional_get(lambda { |env|
[200, { 'last-modified' => (Time.now - 3600).httpdate, 'content-type' => 'text/plain' }, ['TEST']] })
response = Rack::MockRequest.new(app).
get("/", 'HTTP_IF_MODIFIED_SINCE' => bad_timestamp)
response.status.must_equal 200
response.body.must_equal 'TEST'
end
end
|