[deploy] handle rate limit errors gracefully (#7422)

This commit is contained in:
Molly Struve 2020-04-22 08:55:26 -05:00 committed by GitHub
parent 27131f6f42
commit de88a08ebd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 31 additions and 1 deletions

View file

@ -21,6 +21,8 @@ class Api::V0::ApiController < ApplicationController
error_unauthorized
end
rescue_from RateLimitChecker::LimitReached, with: :too_many_requests
protected
def error_unprocessable_entity(message)
@ -35,6 +37,10 @@ class Api::V0::ApiController < ApplicationController
render json: { error: "not found", status: 404 }, status: :not_found
end
def too_many_requests
render json: { error: "too many requests", status: 429 }, status: :too_many_requests
end
def authenticate!
if doorkeeper_token
@user = User.find(doorkeeper_token.resource_owner_id)

View file

@ -7,6 +7,7 @@ class RateLimitChecker
class UploadRateLimitReached < StandardError; end
class DailyFollowAccountLimitReached < StandardError; end
class LimitReached < StandardError; end
def limit_by_action(action)
check_method = "check_#{action}_limit"

View file

@ -11,7 +11,7 @@ module Articles
end
def call
raise if RateLimitChecker.new(user).limit_by_action("published_article_creation")
raise RateLimitChecker::LimitReached if RateLimitChecker.new(user).limit_by_action("published_article_creation")
article = save_article

View file

@ -19,6 +19,7 @@ Honeybadger.configure do |config|
Pundit::NotAuthorizedError,
ActiveRecord::RecordNotFound,
ActiveRecord::QueryCanceled,
RateLimitChecker::LimitReached,
]
config.request.filter_keys += %w[authorization]
config.sidekiq.attempt_threshold = 10

View file

@ -445,6 +445,15 @@ RSpec.describe "Api::V0::Articles", type: :request do
let_it_be(:api_secret) { create(:api_secret) }
let_it_be(:user) { api_secret.user }
context "when creation limit is reached" do
it "returns a 429 status code and error" do
allow(Articles::Creator).to receive(:call).and_raise(RateLimitChecker::LimitReached)
headers = { "api-key" => api_secret.secret, "content-type" => "application/json" }
post api_articles_path, params: { article: { body_markdown: "" } }.to_json, headers: headers
expect(response).to have_http_status(:too_many_requests)
end
end
context "when unauthorized" do
it "fails with no api key" do
post api_articles_path, headers: { "content-type" => "application/json" }

View file

@ -218,4 +218,17 @@ RSpec.describe "Articles", type: :request do
end
end
end
describe "POST /create" do
before { sign_in user }
context "when creation limit is reached" do
it "raises a rate limit reached error" do
allow(Articles::Creator).to receive(:call).and_raise(RateLimitChecker::LimitReached)
expect do
post articles_path, params: { article: { markdown: "123" } }
end.to raise_error(RateLimitChecker::LimitReached)
end
end
end
end