|
25 | 25 | it 'should not create RateLimit headers' do
|
26 | 26 | last_response.header.key?('X-RateLimit-Limit').should be false
|
27 | 27 | last_response.header.key?('X-RateLimit-Remaining').should be false
|
| 28 | + last_response.header.key?('X-RateLimit-Reset').should be false |
28 | 29 | end
|
29 | 30 |
|
30 | 31 | end
|
|
36 | 37 |
|
37 | 38 | let(:request_limit) { (1..10_000).to_a.sample }
|
38 | 39 | let(:request_count) { (1..(request_limit - 10)).to_a.sample }
|
| 40 | + let(:request_period) { rand(60..3600) } |
39 | 41 |
|
40 | 42 | context 'one throttle only' do
|
41 | 43 |
|
42 | 44 | let(:rack_attack_throttle_data) do
|
43 |
| - { "#{throttle_one}" => { count: request_count, limit: request_limit } } |
| 45 | + { "#{throttle_one}" => { count: request_count, limit: request_limit, period: request_period} } |
44 | 46 | end
|
45 | 47 |
|
46 | 48 | it 'should include RateLimit headers' do
|
47 | 49 | last_response.header.key?('X-RateLimit-Limit').should be true
|
48 | 50 | last_response.header.key?('X-RateLimit-Remaining').should be true
|
| 51 | + last_response.header.key?('X-RateLimit-Reset').should be true |
49 | 52 | end
|
50 | 53 |
|
51 | 54 | it 'should return correct rate limit in header' do
|
|
55 | 58 | it 'should return correct remaining calls in header' do
|
56 | 59 | last_response.header['X-RateLimit-Remaining'].to_i.should eq(request_limit - request_count)
|
57 | 60 | end
|
| 61 | + |
| 62 | + it 'should returns the number of seconds remaining in the current throttle period' do |
| 63 | + current_epoch_time = Time.now.to_i |
| 64 | + seconds_until_next_period = request_period - (current_epoch_time % request_period) |
| 65 | + last_response.header['X-RateLimit-Reset'].to_i.should eq(seconds_until_next_period) |
| 66 | + end |
58 | 67 | end
|
59 | 68 |
|
60 | 69 | context 'multiple throttles' do
|
|
69 | 78 |
|
70 | 79 | let(:request_limits) { 3.times.map { (1..10_000).to_a.sample } }
|
71 | 80 | let(:request_counts) { 3.times.map { |index| (1..(request_limits[index] - 10)).to_a.sample } }
|
| 81 | + let(:request_periods) { 3.times.map { rand(60..3600) } } |
72 | 82 |
|
73 | 83 | let(:rack_attack_throttle_data) do
|
74 | 84 | data = {}
|
75 | 85 | [throttle_one, throttle_two, throttle_three].each_with_index do |thr, thr_index|
|
76 |
| - data["#{thr}"] = { count: request_counts[thr_index], limit: request_limits[thr_index] } |
| 86 | + data["#{thr}"] = { count: request_counts[thr_index], limit: request_limits[thr_index], period: request_periods[thr_index] } |
77 | 87 | end
|
78 | 88 | data
|
79 | 89 | end
|
| 90 | + |
80 | 91 | it 'should include RateLimit headers' do
|
81 | 92 | last_response.header.key?('X-RateLimit-Limit').should be true
|
82 | 93 | last_response.header.key?('X-RateLimit-Remaining').should be true
|
| 94 | + last_response.header.key?('X-RateLimit-Reset').should be true |
83 | 95 | end
|
84 | 96 |
|
85 | 97 | describe 'header values' do
|
|
95 | 107 | it 'should return correct remaining calls' do
|
96 | 108 | last_response.header['X-RateLimit-Remaining'].to_i.should eq(request_differences[min_index])
|
97 | 109 | end
|
| 110 | + |
| 111 | + it 'should return the correct number of seconds until the current throttled period expires' do |
| 112 | + current_epoch_time = Time.now.to_i |
| 113 | + seconds_until_next_period = request_periods[min_index] - (current_epoch_time % request_periods[min_index]) |
| 114 | + last_response.header['X-RateLimit-Reset'].to_i.should eq(seconds_until_next_period) |
| 115 | + end |
98 | 116 | end
|
99 | 117 | end
|
100 | 118 | end
|
|
0 commit comments