rack-berater 0.4.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/rack/berater/graphql_prioritizer.rb +31 -0
- data/lib/rack/berater/prioritizer.rb +6 -7
- data/lib/rack/berater/rails_prioritizer.rb +1 -4
- data/lib/rack/berater/rspec.rb +1 -0
- data/lib/rack/berater/version.rb +1 -1
- data/lib/rack/berater.rb +1 -0
- data/spec/graphql_prioritizer_spec.rb +104 -0
- data/spec/limiter_spec.rb +6 -7
- data/spec/prioritizer_spec.rb +25 -26
- data/spec/rails_prioritizer_spec.rb +2 -11
- data/spec/rails_spec.rb +39 -0
- data/spec/rescuer_spec.rb +4 -4
- metadata +17 -16
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 879e22ae9d610e5c47f9866c76409c71cd335558c79d69e43bce71bea1f0d8b8
|
|
4
|
+
data.tar.gz: 7a04e12d16de13936a6ec8e0bad8130c1ab465e5625627d5be9cf24e5e694e8b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 357bc1725eb43ae4ea0a664c648b78aecfd89648606e62b24fac3ff799b19464819f68bdf550ee3f9dc57757377b6c66c5fbea6914a4d45043e830ba427b38fe
|
|
7
|
+
data.tar.gz: 1472454e024edbb12637a886a4e1c91553ae6ac094278801428cec7dc6f8c52a3dad7218acaf811efd9b903390930e9c55c6476eaf9b795672f98c91e80a55fb
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module Rack
|
|
2
|
+
class Berater
|
|
3
|
+
class GraphqlPrioritizer < Prioritizer
|
|
4
|
+
def cache_key_for(env)
|
|
5
|
+
request = Rack::Request.new(env)
|
|
6
|
+
|
|
7
|
+
if request.path == '/graphql'
|
|
8
|
+
parts = [ 'graphql' ]
|
|
9
|
+
|
|
10
|
+
if request.params['operationName']
|
|
11
|
+
parts << request.params['operationName']
|
|
12
|
+
elsif request.params['query']
|
|
13
|
+
op = begin
|
|
14
|
+
GraphQL.parse(request.params['query']).definitions.find do |x|
|
|
15
|
+
x.is_a? GraphQL::Language::Nodes::OperationDefinition
|
|
16
|
+
end
|
|
17
|
+
rescue GraphQL::ParseError
|
|
18
|
+
nil
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
parts << op.name if op
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
parts.join(':')
|
|
25
|
+
else
|
|
26
|
+
super
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -9,15 +9,13 @@ module Rack
|
|
|
9
9
|
def initialize(app, options = {})
|
|
10
10
|
@app = app
|
|
11
11
|
@header = options[:header] || HEADER
|
|
12
|
-
|
|
13
|
-
synchronize { @@cache ||= {} }
|
|
14
12
|
end
|
|
15
13
|
|
|
16
14
|
def call(env)
|
|
17
15
|
priority = env[@header] || env["HTTP_#{@header.upcase.tr('-', '_')}"]
|
|
18
16
|
|
|
19
17
|
if priority
|
|
20
|
-
|
|
18
|
+
self.priority = priority
|
|
21
19
|
return @app.call(env)
|
|
22
20
|
end
|
|
23
21
|
|
|
@@ -25,11 +23,11 @@ module Rack
|
|
|
25
23
|
cached_priority = cache_get(cache_key)
|
|
26
24
|
|
|
27
25
|
if cached_priority
|
|
28
|
-
|
|
26
|
+
self.priority = cached_priority
|
|
29
27
|
end
|
|
30
28
|
|
|
31
29
|
@app.call(env).tap do |status, headers, body|
|
|
32
|
-
app_priority = headers.delete(@header) if headers
|
|
30
|
+
app_priority = (headers.delete(@header) || headers.delete(@header.downcase)) if headers
|
|
33
31
|
|
|
34
32
|
if app_priority && app_priority != cached_priority
|
|
35
33
|
# update cache for next time
|
|
@@ -46,19 +44,20 @@ module Rack
|
|
|
46
44
|
|
|
47
45
|
protected
|
|
48
46
|
|
|
49
|
-
def
|
|
47
|
+
def priority=(priority)
|
|
50
48
|
Thread.current[ENV_KEY] = priority
|
|
51
49
|
end
|
|
52
50
|
|
|
53
51
|
def cache_key_for(env)
|
|
54
52
|
[
|
|
55
|
-
env[Rack::REQUEST_METHOD]
|
|
53
|
+
env[Rack::REQUEST_METHOD],
|
|
56
54
|
|
|
57
55
|
# normalize RESTful paths
|
|
58
56
|
env['PATH_INFO'].gsub(%r{/[0-9]+(/|$)}, '/x\1'),
|
|
59
57
|
].join(':')
|
|
60
58
|
end
|
|
61
59
|
|
|
60
|
+
@@cache = {}
|
|
62
61
|
def cache_get(key)
|
|
63
62
|
synchronize { @@cache[key] }
|
|
64
63
|
end
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
require 'action_controller/metal'
|
|
2
|
-
require 'action_dispatch'
|
|
3
|
-
|
|
4
1
|
module Rack
|
|
5
2
|
class Berater
|
|
6
3
|
class RailsPrioritizer < Prioritizer
|
|
@@ -9,7 +6,7 @@ module Rack
|
|
|
9
6
|
env[Rack::PATH_INFO],
|
|
10
7
|
method: env[Rack::REQUEST_METHOD],
|
|
11
8
|
).values_at(:controller, :action).compact.join('#')
|
|
12
|
-
rescue ActionController::RoutingError
|
|
9
|
+
rescue ActionController::RoutingError, NoMethodError
|
|
13
10
|
super
|
|
14
11
|
end
|
|
15
12
|
end
|
data/lib/rack/berater/rspec.rb
CHANGED
data/lib/rack/berater/version.rb
CHANGED
data/lib/rack/berater.rb
CHANGED
|
@@ -5,6 +5,7 @@ require 'set'
|
|
|
5
5
|
|
|
6
6
|
module Rack
|
|
7
7
|
class Berater
|
|
8
|
+
autoload :GraphqlPrioritizer, 'rack/berater/graphql_prioritizer'
|
|
8
9
|
autoload :Prioritizer, 'rack/berater/prioritizer'
|
|
9
10
|
autoload :RailsPrioritizer, 'rack/berater/rails_prioritizer'
|
|
10
11
|
autoload :Railtie, 'rack/berater/railtie'
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
require 'graphql'
|
|
2
|
+
|
|
3
|
+
class UserType < GraphQL::Schema::Object
|
|
4
|
+
field :name, String, null: false
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
class QueryType < GraphQL::Schema::Object
|
|
8
|
+
field :me, UserType
|
|
9
|
+
|
|
10
|
+
def me
|
|
11
|
+
{ name: 'me' }
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
field :user, UserType do
|
|
15
|
+
argument :id, ID
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def user(id:)
|
|
19
|
+
{ name: "user_#{id}" }
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
class Schema < GraphQL::Schema
|
|
24
|
+
query QueryType
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
class GraphqlController < ActionController::Base
|
|
28
|
+
def execute
|
|
29
|
+
render json: Schema.execute(
|
|
30
|
+
params[:query],
|
|
31
|
+
variables: params[:variables],
|
|
32
|
+
operation_name: params[:operationName]
|
|
33
|
+
)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
describe Rack::Berater::GraphqlPrioritizer do
|
|
38
|
+
before do
|
|
39
|
+
Rails.application = Class.new(Rails::Application) do
|
|
40
|
+
config.eager_load = false
|
|
41
|
+
config.hosts.clear # disable hostname filtering
|
|
42
|
+
# config.logger = ActiveSupport::Logger.new($stdout)
|
|
43
|
+
end
|
|
44
|
+
Rails.application.middleware.use described_class
|
|
45
|
+
Rails.initialize!
|
|
46
|
+
|
|
47
|
+
Rails.application.routes.draw do
|
|
48
|
+
post '/graphql', to: 'graphql#execute'
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
let(:app) { Rails.application }
|
|
53
|
+
let(:query) { 'query Me { me { name } }'}
|
|
54
|
+
|
|
55
|
+
describe '#cache_key_for' do
|
|
56
|
+
subject { described_class.new(app).method(:cache_key_for) }
|
|
57
|
+
|
|
58
|
+
it 'uses the implicit graphql operation name' do
|
|
59
|
+
expect(
|
|
60
|
+
subject.call(Rack::MockRequest.env_for(
|
|
61
|
+
'/graphql',
|
|
62
|
+
params: {
|
|
63
|
+
query: query,
|
|
64
|
+
},
|
|
65
|
+
))
|
|
66
|
+
).to match /graphql:Me/
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it 'uses the explicit graphql operation name param' do
|
|
70
|
+
expect(
|
|
71
|
+
subject.call(Rack::MockRequest.env_for(
|
|
72
|
+
'/graphql',
|
|
73
|
+
params: {
|
|
74
|
+
query: query,
|
|
75
|
+
operationName: 'What',
|
|
76
|
+
},
|
|
77
|
+
))
|
|
78
|
+
).to match /graphql:What/
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
it 'works when operation name is missing' do
|
|
82
|
+
expect(
|
|
83
|
+
subject.call(Rack::MockRequest.env_for('/graphql'))
|
|
84
|
+
).to match /graphql/
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
it 'works when query is invalid' do
|
|
88
|
+
expect(
|
|
89
|
+
subject.call(Rack::MockRequest.env_for(
|
|
90
|
+
'/graphql',
|
|
91
|
+
params: {
|
|
92
|
+
query: 'abc!!!',
|
|
93
|
+
},
|
|
94
|
+
))
|
|
95
|
+
).to match /graphql/
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
it 'falls back to Rack style names' do
|
|
99
|
+
expect(
|
|
100
|
+
subject.call(Rack::MockRequest.env_for('/foo'))
|
|
101
|
+
).to match %r{GET:/foo}
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
data/spec/limiter_spec.rb
CHANGED
|
@@ -9,7 +9,7 @@ describe Rack::Berater do
|
|
|
9
9
|
Rack::Builder.new do
|
|
10
10
|
use Rack::Lint
|
|
11
11
|
run (lambda do |env|
|
|
12
|
-
[200, {'
|
|
12
|
+
[200, {'content-type' => 'text/plain'}, ['OK']]
|
|
13
13
|
end)
|
|
14
14
|
end
|
|
15
15
|
end
|
|
@@ -22,8 +22,8 @@ describe Rack::Berater do
|
|
|
22
22
|
|
|
23
23
|
it 'has the correct headers' do
|
|
24
24
|
expect(response.headers).to eq({
|
|
25
|
-
'
|
|
26
|
-
'
|
|
25
|
+
'content-type' => 'text/plain',
|
|
26
|
+
'content-length' => '2',
|
|
27
27
|
})
|
|
28
28
|
end
|
|
29
29
|
|
|
@@ -50,7 +50,7 @@ describe Rack::Berater do
|
|
|
50
50
|
end
|
|
51
51
|
|
|
52
52
|
context 'when operating beyond limits' do
|
|
53
|
-
|
|
53
|
+
let(:limiter) { ::Berater::Inhibitor.new }
|
|
54
54
|
|
|
55
55
|
it 'returns an error' do
|
|
56
56
|
expect(response.status).to eq 429
|
|
@@ -59,8 +59,7 @@ describe Rack::Berater do
|
|
|
59
59
|
end
|
|
60
60
|
|
|
61
61
|
context 'when limiter is a proc' do
|
|
62
|
-
let(:
|
|
63
|
-
let(:limiter) { Proc.new { limiter_instance } }
|
|
62
|
+
let(:limiter) { Proc.new { ::Berater::Unlimiter.new } }
|
|
64
63
|
|
|
65
64
|
include_examples 'works nominally'
|
|
66
65
|
|
|
@@ -70,7 +69,7 @@ describe Rack::Berater do
|
|
|
70
69
|
end
|
|
71
70
|
|
|
72
71
|
context 'when operating beyond limits' do
|
|
73
|
-
|
|
72
|
+
let(:limiter) { Proc.new { ::Berater::Inhibitor.new } }
|
|
74
73
|
|
|
75
74
|
it 'returns an error' do
|
|
76
75
|
expect(response.status).to eq 429
|
data/spec/prioritizer_spec.rb
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
describe Rack::Berater::Prioritizer do
|
|
2
|
-
let(:cache) { described_class.class_variable_get(:@@cache) }
|
|
3
|
-
|
|
4
2
|
describe '#call' do
|
|
5
3
|
subject { described_class.new(app) }
|
|
6
4
|
|
|
7
|
-
let(:app) { ->(*) { [200, {'
|
|
5
|
+
let(:app) { ->(*) { [200, {'content-type' => 'text/plain'}, ['OK']] } }
|
|
8
6
|
let(:cache_key) { subject.send(:cache_key_for, env) }
|
|
9
7
|
let(:env) { Rack::MockRequest.env_for('/') }
|
|
10
8
|
|
|
@@ -30,7 +28,7 @@ describe Rack::Berater::Prioritizer do
|
|
|
30
28
|
after { subject.call(env) }
|
|
31
29
|
|
|
32
30
|
it 'sets the priority accordingly' do
|
|
33
|
-
is_expected.to receive(:
|
|
31
|
+
is_expected.to receive(:priority=).with(priority)
|
|
34
32
|
end
|
|
35
33
|
|
|
36
34
|
it 'updates the global priority during the request' do
|
|
@@ -57,12 +55,12 @@ describe Rack::Berater::Prioritizer do
|
|
|
57
55
|
after { subject.call(env) }
|
|
58
56
|
|
|
59
57
|
it 'uses the header' do
|
|
60
|
-
is_expected.to receive(:
|
|
58
|
+
is_expected.to receive(:priority=).with(priority)
|
|
61
59
|
end
|
|
62
60
|
|
|
63
61
|
it 'ignores any cached value' do
|
|
64
62
|
allow(subject).to receive(:cache_get).with(cache_key).and_return('123')
|
|
65
|
-
is_expected.to receive(:
|
|
63
|
+
is_expected.to receive(:priority=).with(priority)
|
|
66
64
|
end
|
|
67
65
|
|
|
68
66
|
it 'resets the priority after the request completes' do
|
|
@@ -100,6 +98,21 @@ describe Rack::Berater::Prioritizer do
|
|
|
100
98
|
end
|
|
101
99
|
end
|
|
102
100
|
|
|
101
|
+
context 'when the app returns a lowercase priority header, per Rack 3' do
|
|
102
|
+
let(:app) do
|
|
103
|
+
->(*) { [200, { described_class::HEADER.downcase => priority }, ['OK']] }
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
let(:priority) { '5' }
|
|
107
|
+
|
|
108
|
+
it 'caches the priority and removes the header' do
|
|
109
|
+
is_expected.to receive(:cache_set).with(cache_key, priority)
|
|
110
|
+
|
|
111
|
+
_, headers, _ = subject.call(env)
|
|
112
|
+
expect(headers).to be_empty
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
103
116
|
it 'does not update the cache when no priority is returned' do
|
|
104
117
|
is_expected.not_to receive(:cache_set)
|
|
105
118
|
subject.call(env)
|
|
@@ -113,7 +126,7 @@ describe Rack::Berater::Prioritizer do
|
|
|
113
126
|
let(:env) { Rack::MockRequest.env_for('/') }
|
|
114
127
|
|
|
115
128
|
it 'combines the verb and path' do
|
|
116
|
-
is_expected.to match %r{
|
|
129
|
+
is_expected.to match %r{GET:/$}
|
|
117
130
|
end
|
|
118
131
|
end
|
|
119
132
|
|
|
@@ -121,7 +134,7 @@ describe Rack::Berater::Prioritizer do
|
|
|
121
134
|
let(:env) { Rack::MockRequest.env_for('/', method: 'PUT') }
|
|
122
135
|
|
|
123
136
|
it 'combines the verb and path' do
|
|
124
|
-
is_expected.to match %r{
|
|
137
|
+
is_expected.to match %r{PUT:/$}
|
|
125
138
|
end
|
|
126
139
|
end
|
|
127
140
|
|
|
@@ -129,7 +142,7 @@ describe Rack::Berater::Prioritizer do
|
|
|
129
142
|
let(:env) { Rack::MockRequest.env_for('/user/123') }
|
|
130
143
|
|
|
131
144
|
it 'normalizes the id' do
|
|
132
|
-
is_expected.to match %r{
|
|
145
|
+
is_expected.to match %r{GET:/user/x$}
|
|
133
146
|
end
|
|
134
147
|
end
|
|
135
148
|
|
|
@@ -137,7 +150,7 @@ describe Rack::Berater::Prioritizer do
|
|
|
137
150
|
let(:env) { Rack::MockRequest.env_for('/user/123/') }
|
|
138
151
|
|
|
139
152
|
it 'normalizes the id and keeps the trailing slash' do
|
|
140
|
-
is_expected.to match %r{
|
|
153
|
+
is_expected.to match %r{GET:/user/x/$}
|
|
141
154
|
end
|
|
142
155
|
end
|
|
143
156
|
|
|
@@ -145,7 +158,7 @@ describe Rack::Berater::Prioritizer do
|
|
|
145
158
|
let(:env) { Rack::MockRequest.env_for('/user/123/friend/456') }
|
|
146
159
|
|
|
147
160
|
it 'normalizes both ids' do
|
|
148
|
-
is_expected.to match %r{
|
|
161
|
+
is_expected.to match %r{GET:/user/x/friend/x$}
|
|
149
162
|
end
|
|
150
163
|
end
|
|
151
164
|
end
|
|
@@ -157,7 +170,7 @@ describe Rack::Berater::Prioritizer do
|
|
|
157
170
|
|
|
158
171
|
let(:app) do
|
|
159
172
|
headers = {
|
|
160
|
-
'
|
|
173
|
+
'content-type' => 'text/plain',
|
|
161
174
|
described_class::HEADER => app_priority,
|
|
162
175
|
}.compact
|
|
163
176
|
|
|
@@ -188,7 +201,6 @@ describe Rack::Berater::Prioritizer do
|
|
|
188
201
|
|
|
189
202
|
it 'parses the priority returned from the app' do
|
|
190
203
|
expect(call).to be_empty
|
|
191
|
-
expect(cache.values).to include app_priority
|
|
192
204
|
end
|
|
193
205
|
|
|
194
206
|
it 'uses the cached priority for subsequent calls' do
|
|
@@ -196,18 +208,5 @@ describe Rack::Berater::Prioritizer do
|
|
|
196
208
|
expect(call).to eq app_priority
|
|
197
209
|
end
|
|
198
210
|
end
|
|
199
|
-
|
|
200
|
-
# context 'when two different endpoints are called' do
|
|
201
|
-
# fit 'parses and caches each priority' do
|
|
202
|
-
# @app_priority = '6'
|
|
203
|
-
# expect(call('/six')).to be_empty
|
|
204
|
-
|
|
205
|
-
# expect(call('/six')).to eq '6'
|
|
206
|
-
|
|
207
|
-
# @app_priority = '9'
|
|
208
|
-
# expect(call('/nine')).to be_empty
|
|
209
|
-
# expect(call('/nine')).to '9'
|
|
210
|
-
# end
|
|
211
|
-
# end
|
|
212
211
|
end
|
|
213
212
|
end
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
require 'rspec/rails'
|
|
2
|
-
|
|
3
1
|
describe Rack::Berater::RailsPrioritizer do
|
|
4
2
|
before do
|
|
5
3
|
class EchoController < ActionController::Base
|
|
@@ -35,13 +33,6 @@ describe Rack::Berater::RailsPrioritizer do
|
|
|
35
33
|
end
|
|
36
34
|
|
|
37
35
|
let(:app) { Rails.application }
|
|
38
|
-
let(:middleware) { described_class.new(app) }
|
|
39
|
-
|
|
40
|
-
after do
|
|
41
|
-
Rails.application = nil
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
let(:cache) { described_class.class_variable_get(:@@cache) }
|
|
45
36
|
|
|
46
37
|
describe '#cache_key_for' do
|
|
47
38
|
subject { described_class.new(app).method(:cache_key_for) }
|
|
@@ -63,13 +54,13 @@ describe Rack::Berater::RailsPrioritizer do
|
|
|
63
54
|
it 'falls back to Rack style names' do
|
|
64
55
|
expect(
|
|
65
56
|
subject.call(Rack::MockRequest.env_for('/nine'))
|
|
66
|
-
).to match %r{
|
|
57
|
+
).to match %r{GET:/nine}
|
|
67
58
|
end
|
|
68
59
|
|
|
69
60
|
it 'works with redirects' do
|
|
70
61
|
expect(
|
|
71
62
|
subject.call(Rack::MockRequest.env_for('/redirect'))
|
|
72
|
-
).to match %r{
|
|
63
|
+
).to match %r{GET:/redirect}
|
|
73
64
|
end
|
|
74
65
|
end
|
|
75
66
|
|
data/spec/rails_spec.rb
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
require 'rspec/rails'
|
|
2
|
+
|
|
3
|
+
describe Rack::Berater do
|
|
4
|
+
before do
|
|
5
|
+
class OkController < ActionController::Base
|
|
6
|
+
around_action :limit
|
|
7
|
+
|
|
8
|
+
def limit(&block)
|
|
9
|
+
Berater(:key, 1) { yield }
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def index
|
|
13
|
+
head :ok
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
Rails.application = Class.new(Rails::Application) do
|
|
18
|
+
config.eager_load = false
|
|
19
|
+
config.hosts.clear # disable hostname filtering
|
|
20
|
+
# config.logger = ActiveSupport::Logger.new($stdout)
|
|
21
|
+
end
|
|
22
|
+
Rails.application.middleware.use described_class
|
|
23
|
+
Rails.initialize!
|
|
24
|
+
|
|
25
|
+
Rails.application.routes.draw do
|
|
26
|
+
get '/' => 'ok#index'
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
let(:app) { Rails.application }
|
|
31
|
+
|
|
32
|
+
it { expect(get('/')).to be_ok }
|
|
33
|
+
|
|
34
|
+
context 'when past limits' do
|
|
35
|
+
before { Berater.test_mode = :fail }
|
|
36
|
+
|
|
37
|
+
it { expect(get('/').status).to be 429 }
|
|
38
|
+
end
|
|
39
|
+
end
|
data/spec/rescuer_spec.rb
CHANGED
|
@@ -3,8 +3,8 @@ describe Rack::Berater do
|
|
|
3
3
|
Rack::Builder.new do
|
|
4
4
|
use Rack::Lint
|
|
5
5
|
run (lambda do |env|
|
|
6
|
-
Berater
|
|
7
|
-
[200, {'
|
|
6
|
+
Berater(:key, 1) do
|
|
7
|
+
[200, {'content-type' => 'text/plain'}, ['OK']]
|
|
8
8
|
end
|
|
9
9
|
end)
|
|
10
10
|
end
|
|
@@ -18,8 +18,8 @@ describe Rack::Berater do
|
|
|
18
18
|
|
|
19
19
|
it 'has the correct headers' do
|
|
20
20
|
expect(response.headers).to eq({
|
|
21
|
-
'
|
|
22
|
-
'
|
|
21
|
+
'content-type' => 'text/plain',
|
|
22
|
+
'content-length' => '2',
|
|
23
23
|
})
|
|
24
24
|
end
|
|
25
25
|
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rack-berater
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Daniel Pepper
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: berater
|
|
@@ -39,7 +38,7 @@ dependencies:
|
|
|
39
38
|
- !ruby/object:Gem::Version
|
|
40
39
|
version: '0'
|
|
41
40
|
- !ruby/object:Gem::Dependency
|
|
42
|
-
name:
|
|
41
|
+
name: debug
|
|
43
42
|
requirement: !ruby/object:Gem::Requirement
|
|
44
43
|
requirements:
|
|
45
44
|
- - ">="
|
|
@@ -53,7 +52,7 @@ dependencies:
|
|
|
53
52
|
- !ruby/object:Gem::Version
|
|
54
53
|
version: '0'
|
|
55
54
|
- !ruby/object:Gem::Dependency
|
|
56
|
-
name:
|
|
55
|
+
name: graphql
|
|
57
56
|
requirement: !ruby/object:Gem::Requirement
|
|
58
57
|
requirements:
|
|
59
58
|
- - ">="
|
|
@@ -86,14 +85,14 @@ dependencies:
|
|
|
86
85
|
requirements:
|
|
87
86
|
- - ">="
|
|
88
87
|
- !ruby/object:Gem::Version
|
|
89
|
-
version: '
|
|
88
|
+
version: '7'
|
|
90
89
|
type: :development
|
|
91
90
|
prerelease: false
|
|
92
91
|
version_requirements: !ruby/object:Gem::Requirement
|
|
93
92
|
requirements:
|
|
94
93
|
- - ">="
|
|
95
94
|
- !ruby/object:Gem::Version
|
|
96
|
-
version: '
|
|
95
|
+
version: '7'
|
|
97
96
|
- !ruby/object:Gem::Dependency
|
|
98
97
|
name: rspec
|
|
99
98
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -128,37 +127,38 @@ dependencies:
|
|
|
128
127
|
requirements:
|
|
129
128
|
- - ">="
|
|
130
129
|
- !ruby/object:Gem::Version
|
|
131
|
-
version: '
|
|
130
|
+
version: '1'
|
|
132
131
|
type: :development
|
|
133
132
|
prerelease: false
|
|
134
133
|
version_requirements: !ruby/object:Gem::Requirement
|
|
135
134
|
requirements:
|
|
136
135
|
- - ">="
|
|
137
136
|
- !ruby/object:Gem::Version
|
|
138
|
-
version: '
|
|
137
|
+
version: '1'
|
|
139
138
|
description: limit incoming requests
|
|
140
|
-
email:
|
|
141
139
|
executables: []
|
|
142
140
|
extensions: []
|
|
143
141
|
extra_rdoc_files: []
|
|
144
142
|
files:
|
|
145
143
|
- lib/rack-berater.rb
|
|
146
144
|
- lib/rack/berater.rb
|
|
145
|
+
- lib/rack/berater/graphql_prioritizer.rb
|
|
147
146
|
- lib/rack/berater/prioritizer.rb
|
|
148
147
|
- lib/rack/berater/rails_prioritizer.rb
|
|
149
148
|
- lib/rack/berater/railtie.rb
|
|
150
149
|
- lib/rack/berater/rspec.rb
|
|
151
150
|
- lib/rack/berater/version.rb
|
|
151
|
+
- spec/graphql_prioritizer_spec.rb
|
|
152
152
|
- spec/limiter_spec.rb
|
|
153
153
|
- spec/prioritizer_spec.rb
|
|
154
154
|
- spec/rails_prioritizer_spec.rb
|
|
155
|
+
- spec/rails_spec.rb
|
|
155
156
|
- spec/railtie_spec.rb
|
|
156
157
|
- spec/rescuer_spec.rb
|
|
157
158
|
homepage: https://github.com/dpep/rack-berater
|
|
158
159
|
licenses:
|
|
159
160
|
- MIT
|
|
160
161
|
metadata: {}
|
|
161
|
-
post_install_message:
|
|
162
162
|
rdoc_options: []
|
|
163
163
|
require_paths:
|
|
164
164
|
- lib
|
|
@@ -166,20 +166,21 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
166
166
|
requirements:
|
|
167
167
|
- - ">="
|
|
168
168
|
- !ruby/object:Gem::Version
|
|
169
|
-
version: '
|
|
169
|
+
version: '3.3'
|
|
170
170
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
171
171
|
requirements:
|
|
172
172
|
- - ">="
|
|
173
173
|
- !ruby/object:Gem::Version
|
|
174
174
|
version: '0'
|
|
175
175
|
requirements: []
|
|
176
|
-
rubygems_version: 3.
|
|
177
|
-
signing_key:
|
|
176
|
+
rubygems_version: 3.6.9
|
|
178
177
|
specification_version: 4
|
|
179
178
|
summary: Rack::Berater
|
|
180
179
|
test_files:
|
|
180
|
+
- spec/graphql_prioritizer_spec.rb
|
|
181
|
+
- spec/limiter_spec.rb
|
|
182
|
+
- spec/prioritizer_spec.rb
|
|
181
183
|
- spec/rails_prioritizer_spec.rb
|
|
184
|
+
- spec/rails_spec.rb
|
|
182
185
|
- spec/railtie_spec.rb
|
|
183
186
|
- spec/rescuer_spec.rb
|
|
184
|
-
- spec/prioritizer_spec.rb
|
|
185
|
-
- spec/limiter_spec.rb
|