Merge pull request #1330 from okriuchykhin/ok_SCI_2770

Add request rate throttling for API [SCI-2770]
This commit is contained in:
Alex Kriuchykhin 2018-10-19 09:38:31 +02:00 committed by GitHub
commit e9b64b65a3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 34 additions and 1 deletions

View file

@ -26,6 +26,7 @@ gem 'active_model_serializers', '~> 0.10.7'
gem 'json-jwt'
gem 'jwt', '~> 1.5'
gem 'kaminari'
gem 'rack-attack'
# JS datetime library, requirement of datetime picker
gem 'momentjs-rails', '~> 2.17.1'

View file

@ -357,6 +357,8 @@ GEM
public_suffix (3.0.2)
puma (3.11.2)
rack (2.0.5)
rack-attack (5.4.1)
rack (>= 1.0, < 3)
rack-test (1.1.0)
rack (>= 1.0, < 3)
rails (5.1.6)
@ -595,6 +597,7 @@ DEPENDENCIES
pry-byebug
pry-rails
puma
rack-attack
rails (= 5.1.6)
rails-controller-testing
rails_12factor

View file

@ -85,7 +85,7 @@ tests-ci:
@docker-compose run --rm web bash -c "bundle install && npm install"
@docker-compose up -d webpack
@docker-compose ps
@docker-compose run -e ENABLE_EMAIL_CONFIRMATIONS=false -e MAILER_PORT=$MAILER_PORT -e SMTP_DOMAIN=$SMTP_DOMAIN -e SMTP_USERNAME=$SMTP_USERNAME -e SMTP_PASSWORD=$SMTP_PASSWORD -e SMTP_ADDRESS=$SMTP_ADDRESS -e PAPERCLIP_HASH_SECRET=PAPERCLIP_HASH_SECRET -e MAIL_SERVER_URL=localhost -e PAPERCLIP_STORAGE=filesystem -e ENABLE_RECAPTCHA=false -e ENABLE_USER_CONFIRMATION=false -e ENABLE_USER_REGISTRATION=true --rm web bash -c "rake db:create db:migrate && rake db:migrate RAILS_ENV=test && npm install && bundle exec rspec && bundle exec cucumber"
@docker-compose run -e ENABLE_EMAIL_CONFIRMATIONS=false -e MAILER_PORT=$MAILER_PORT -e SMTP_DOMAIN=$SMTP_DOMAIN -e SMTP_USERNAME=$SMTP_USERNAME -e SMTP_PASSWORD=$SMTP_PASSWORD -e SMTP_ADDRESS=$SMTP_ADDRESS -e PAPERCLIP_HASH_SECRET=PAPERCLIP_HASH_SECRET -e MAIL_SERVER_URL=localhost -e PAPERCLIP_STORAGE=filesystem -e ENABLE_RECAPTCHA=false -e ENABLE_USER_CONFIRMATION=false -e ENABLE_USER_REGISTRATION=true -e CORE_API_RATE_LIMIT=1000000 --rm web bash -c "rake db:create db:migrate && rake db:migrate RAILS_ENV=test && npm install && bundle exec rspec && bundle exec cucumber"
console:
@$(MAKE) rails cmd="rails console"

View file

@ -17,6 +17,7 @@ module Api
attr_accessor :core_api_token_iss
attr_accessor :azure_ad_apps
attr_accessor :core_api_v1_preview
attr_accessor :core_api_rate_limit
def initialize
@core_api_sign_alg = 'HS256'
@ -24,6 +25,7 @@ module Api
@core_api_token_iss = 'SciNote'
@azure_ad_apps = {}
@core_api_v1_preview = false
@core_api_rate_limit = 1000
end
end
end

View file

@ -15,6 +15,9 @@ module Scinote
# Application configuration should go into files in config/initializers
# -- all .rb files in that directory are automatically loaded.
# Add rack-attack middleware for request rate limiting
config.middleware.use Rack::Attack
# Swap the Rack::MethodOverride with a wrapped middleware for WOPI handling
require_relative '../app/middlewares/wopi_method_override'
config.middleware.swap Rack::MethodOverride, WopiMethodOverride

View file

@ -9,6 +9,8 @@ Api.configure do |config|
config.core_api_token_iss = ENV['CORE_API_TOKEN_ISS']
end
config.core_api_rate_limit = ENV['CORE_API_RATE_LIMIT'].to_i || 1000
config.core_api_v1_preview = true if ENV['CORE_API_V1_PREVIEW']
Paperclip::DataUriAdapter.register if ENV['CORE_API_V1_PREVIEW']

View file

@ -0,0 +1,22 @@
# frozen_string_literal: true
Rack::Attack.throttle('api requests by ip',
limit: Api.configuration.core_api_rate_limit,
period: 60) do |request|
request.ip if request.path =~ %r{^\/api\/}
end
Rack::Attack.throttled_response = lambda do |env|
match_data = env['rack.attack.match_data']
now = match_data[:epoch_time]
headers = {
'RateLimit-Limit' => match_data[:limit].to_s,
'RateLimit-Remaining' => '0',
'RateLimit-Reset' => (
now + (match_data[:period] - now % match_data[:period])
).to_s
}
[429, headers, ["Throttled\n"]]
end