rack_attack_spec.rb 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. # frozen_string_literal: true
  2. require 'rails_helper'
  3. describe Rack::Attack do
  4. include Rack::Test::Methods
  5. def app
  6. Rails.application
  7. end
  8. shared_examples 'throttled endpoint' do
  9. context 'when the number of requests is lower than the limit' do
  10. it 'does not change the request status' do
  11. limit.times do
  12. request.call
  13. expect(last_response.status).to_not eq(429)
  14. end
  15. end
  16. end
  17. context 'when the number of requests is higher than the limit' do
  18. it 'returns http too many requests' do
  19. (limit * 2).times do |i|
  20. request.call
  21. expect(last_response.status).to eq(429) if i > limit
  22. end
  23. end
  24. end
  25. end
  26. let(:remote_ip) { '1.2.3.5' }
  27. describe 'throttle excessive sign-up requests by IP address' do
  28. context 'through the website' do
  29. let(:limit) { 25 }
  30. let(:request) { -> { post path, {}, 'REMOTE_ADDR' => remote_ip } }
  31. context 'for exact path' do
  32. let(:path) { '/auth' }
  33. it_behaves_like 'throttled endpoint'
  34. end
  35. context 'for path with format' do
  36. let(:path) { '/auth.html' }
  37. it_behaves_like 'throttled endpoint'
  38. end
  39. end
  40. context 'through the API' do
  41. let(:limit) { 5 }
  42. let(:request) { -> { post path, {}, 'REMOTE_ADDR' => remote_ip } }
  43. context 'for exact path' do
  44. let(:path) { '/api/v1/accounts' }
  45. it_behaves_like 'throttled endpoint'
  46. end
  47. context 'for path with format' do
  48. let(:path) { '/api/v1/accounts.json' }
  49. it 'returns http not found' do
  50. request.call
  51. expect(last_response.status).to eq(404)
  52. end
  53. end
  54. end
  55. end
  56. describe 'throttle excessive sign-in requests by IP address' do
  57. let(:limit) { 25 }
  58. let(:request) { -> { post path, {}, 'REMOTE_ADDR' => remote_ip } }
  59. context 'for exact path' do
  60. let(:path) { '/auth/sign_in' }
  61. it_behaves_like 'throttled endpoint'
  62. end
  63. context 'for path with format' do
  64. let(:path) { '/auth/sign_in.html' }
  65. it_behaves_like 'throttled endpoint'
  66. end
  67. end
  68. end