@@ -5,10 +5,12 @@ module Middleware
55 RSpec . describe ServiceBrokerRateLimiter do
66 let ( :app ) { double ( :app ) }
77 let ( :logger ) { double }
8- let ( :path_info ) { '/v3/service_instances' }
8+ let ( :instance ) { VCAP ::CloudController ::Service . make ( instances_retrievable : true ) }
9+ let ( :path_info ) { '/v2/service_instances' }
910 let ( :user_guid ) { SecureRandom . uuid }
1011 let ( :user_env ) { { 'cf.user_guid' => user_guid , 'PATH_INFO' => path_info } }
11- let ( :fake_request ) { instance_double ( ActionDispatch ::Request , fullpath : '/v3/service_instances' , method : 'POST' ) }
12+ let ( :env ) { { 'cf.user_guid' => user_guid , 'PATH_INFO' => path , 'REQUEST_METHOD' => request_method } }
13+ let ( :fake_request ) { instance_double ( ActionDispatch ::Request , fullpath : '/v2/service_instances' , method : 'POST' ) }
1214 let ( :max_concurrent_requests ) { 1 }
1315 let ( :broker_timeout ) { 60 }
1416 let ( :middleware ) do
@@ -39,16 +41,6 @@ module Middleware
3941 expect ( status ) . to eq ( 200 )
4042 end
4143
42- it 'does not allow more than the max number of concurrent requests' do
43- threads = 2 . times . map { Thread . new { Thread . current [ :status ] , = middleware . call ( user_env ) } }
44- statuses = threads . map { |t | t . join [ :status ] }
45-
46- expect ( statuses ) . to include ( 200 )
47- expect ( statuses ) . to include ( 429 )
48- expect ( app ) . to have_received ( :call ) . once
49- expect ( logger ) . to have_received ( :info ) . with ( "Service broker concurrent rate limit exceeded for user '#{ user_guid } '" )
50- end
51-
5244 it 'counts concurrent requests per user' do
5345 other_user_env = { 'cf.user_guid' => 'other_user_guid' , 'PATH_INFO' => path_info }
5446 threads = [ user_env , other_user_env ] . map do |env |
@@ -117,20 +109,79 @@ module Middleware
117109 end
118110 end
119111 end
112+
113+ shared_examples 'rate-limited endpoint' do
114+ it 'does not allow more than the max number of concurrent requests' do
115+ allow ( app ) . to receive ( :call ) do
116+ sleep ( 1 )
117+ [ 200 , { } , 'a body' ]
118+ end
119+
120+ threads = 2 . times . map { Thread . new { middleware . call ( env ) } }
121+ statuses = threads . map ( &:join ) . map ( &:value ) . map ( &:first )
122+
123+ expect ( statuses ) . to include ( 200 )
124+ expect ( statuses ) . to include ( 429 )
125+ expect ( app ) . to have_received ( :call ) . once
126+ expect ( logger ) . to have_received ( :info ) . with ( "Service broker concurrent rate limit exceeded for user '#{ user_guid } '" )
127+ end
128+ end
129+
130+ v2_rate_limited_service_endpoints = %w[ /v2/service_instances /v2/service_bindings /v2/service_keys ]
131+
132+ methods = %w[ PUT POST DELETE ]
133+
134+ v2_rate_limited_service_endpoints . each do |endpoint |
135+ methods . each do |method |
136+ context "#{ endpoint } #{ method } endpoint" do
137+ let ( :path ) { endpoint }
138+ let ( :request_method ) { method }
139+ let ( :fake_request ) { instance_double ( ActionDispatch ::Request , fullpath : endpoint , method : method ) }
140+
141+ include_examples 'rate-limited endpoint'
142+ end
143+ end
144+ end
145+
146+ v3_rate_limited_service_endpoints = %w[ /v3/service_instances/:guid/parameters /v3/service_credential_bindings/:guid/parameters /v3/service_route_bindings/:guid/parameters ]
147+
148+ v3_rate_limited_service_endpoints . each do |endpoint |
149+ context "#{ endpoint } GET" do
150+ let ( :path ) { endpoint . gsub ( ':guid' , instance . guid . to_s ) }
151+ let ( :request_method ) { 'GET' }
152+ let ( :fake_request ) { instance_double ( ActionDispatch ::Request , fullpath : path , method : request_method ) }
153+
154+ include_examples 'rate-limited endpoint'
155+ end
156+ end
120157 end
121158
122159 describe 'excluded requests' do
123- let ( :fake_request ) { instance_double ( ActionDispatch ::Request , fullpath : '/v3/service_instances' , method : 'POST' ) }
160+ shared_examples 'non-rate-limited endpoint' do
161+ it 'allows concurrent requests without limits' do
162+ threads = 2 . times . map { Thread . new { middleware . call ( env ) } }
163+ statuses = threads . map ( &:join ) . map ( &:value ) . map ( &:first )
164+
165+ expect ( statuses ) . to all ( eq ( 200 ) )
166+ expect ( app ) . to have_received ( :call ) . twice
167+ expect ( logger ) . not_to have_received ( :info )
168+ end
169+ end
124170
125- it 'allows requests that are no longer rate limited' do
126- status , = middleware . call ( user_env )
127- expect ( status ) . to eq ( 200 )
171+ v3_not_rate_limited_service_endpoints = %w[ /v3/service_instances /v3/service_credential_bindings /v3/service_route_bindings ]
128172
129- status , = middleware . call ( user_env )
130- expect ( status ) . to eq ( 200 )
173+ methods = %w[ POST PATCH DELETE ]
174+
175+ v3_not_rate_limited_service_endpoints . each do |endpoint |
176+ methods . each do |method |
177+ context "#{ endpoint } #{ method } - non-rate-limited" do
178+ let ( :path ) { endpoint }
179+ let ( :request_method ) { method }
180+ let ( :fake_request ) { instance_double ( ActionDispatch ::Request , fullpath : endpoint , method : method ) }
131181
132- statuses = 2 . times . map { middleware . call ( user_env ) . first }
133- expect ( statuses ) . to contain_exactly ( 200 , 200 )
182+ include_examples 'non-rate-limited endpoint'
183+ end
184+ end
134185 end
135186 end
136187
0 commit comments