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
|