about summary refs log tree commit diff
path: root/app/controllers
diff options
context:
space:
mode:
authorThibG <thib@sitedethib.com>2020-03-08 22:09:53 +0100
committerGitHub <noreply@github.com>2020-03-08 22:09:53 +0100
commit840b17e3444f9a68d3639f1ffeb326e8cb1e03b1 (patch)
tree8254538ed33f4c4b974b5379f3b5a0b489ba095a /app/controllers
parent13ef4d5fb0dbb66074f42df7989ae40509a4724f (diff)
parent9c2922958783f7e499cdda5bb874d6096e47eb0a (diff)
Merge pull request #1297 from ThibG/glitch-soc/merge-upstream
Merge upstream changes
Diffstat (limited to 'app/controllers')
-rw-r--r--app/controllers/account_follow_controller.rb2
-rw-r--r--app/controllers/admin/site_uploads_controller.rb21
-rw-r--r--app/controllers/api/base_controller.rb4
-rw-r--r--app/controllers/api/v1/accounts/follower_accounts_controller.rb2
-rw-r--r--app/controllers/api/v1/accounts/following_accounts_controller.rb2
-rw-r--r--app/controllers/api/v1/accounts/identity_proofs_controller.rb2
-rw-r--r--app/controllers/api/v1/accounts/lists_controller.rb2
-rw-r--r--app/controllers/api/v1/accounts/pins_controller.rb2
-rw-r--r--app/controllers/api/v1/accounts/relationships_controller.rb2
-rw-r--r--app/controllers/api/v1/accounts/search_controller.rb2
-rw-r--r--app/controllers/api/v1/accounts/statuses_controller.rb2
-rw-r--r--app/controllers/api/v1/accounts_controller.rb4
-rw-r--r--app/controllers/api/v1/apps/credentials_controller.rb2
-rw-r--r--app/controllers/api/v1/blocks_controller.rb2
-rw-r--r--app/controllers/api/v1/bookmarks_controller.rb2
-rw-r--r--app/controllers/api/v1/conversations_controller.rb2
-rw-r--r--app/controllers/api/v1/custom_emojis_controller.rb2
-rw-r--r--app/controllers/api/v1/domain_blocks_controller.rb2
-rw-r--r--app/controllers/api/v1/endorsements_controller.rb2
-rw-r--r--app/controllers/api/v1/favourites_controller.rb2
-rw-r--r--app/controllers/api/v1/featured_tags/suggestions_controller.rb3
-rw-r--r--app/controllers/api/v1/filters_controller.rb2
-rw-r--r--app/controllers/api/v1/instances/activity_controller.rb2
-rw-r--r--app/controllers/api/v1/instances/peers_controller.rb2
-rw-r--r--app/controllers/api/v1/instances_controller.rb2
-rw-r--r--app/controllers/api/v1/media_controller.rb2
-rw-r--r--app/controllers/api/v1/mutes_controller.rb2
-rw-r--r--app/controllers/api/v1/notifications_controller.rb2
-rw-r--r--app/controllers/api/v1/polls/votes_controller.rb2
-rw-r--r--app/controllers/api/v1/polls_controller.rb2
-rw-r--r--app/controllers/api/v1/preferences_controller.rb2
-rw-r--r--app/controllers/api/v1/reports_controller.rb2
-rw-r--r--app/controllers/api/v1/statuses/bookmarks_controller.rb2
-rw-r--r--app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb2
-rw-r--r--app/controllers/api/v1/statuses/favourites_controller.rb2
-rw-r--r--app/controllers/api/v1/statuses/mutes_controller.rb2
-rw-r--r--app/controllers/api/v1/statuses/pins_controller.rb2
-rw-r--r--app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb2
-rw-r--r--app/controllers/api/v1/statuses/reblogs_controller.rb3
-rw-r--r--app/controllers/api/v1/statuses_controller.rb5
-rw-r--r--app/controllers/api/v1/streaming_controller.rb2
-rw-r--r--app/controllers/api/v1/suggestions_controller.rb2
-rw-r--r--app/controllers/api/v1/timelines/home_controller.rb2
-rw-r--r--app/controllers/api/v1/timelines/public_controller.rb2
-rw-r--r--app/controllers/api/v1/timelines/tag_controller.rb2
-rw-r--r--app/controllers/api/v1/trends_controller.rb2
-rw-r--r--app/controllers/api/v2/search_controller.rb2
-rw-r--r--app/controllers/api/web/embeds_controller.rb2
-rw-r--r--app/controllers/api/web/push_subscriptions_controller.rb2
-rw-r--r--app/controllers/api/web/settings_controller.rb2
-rw-r--r--app/controllers/application_controller.rb5
-rw-r--r--app/controllers/authorize_interactions_controller.rb2
-rw-r--r--app/controllers/concerns/rate_limit_headers.rb16
53 files changed, 54 insertions, 97 deletions
diff --git a/app/controllers/account_follow_controller.rb b/app/controllers/account_follow_controller.rb
index 185a355f8..33394074d 100644
--- a/app/controllers/account_follow_controller.rb
+++ b/app/controllers/account_follow_controller.rb
@@ -6,7 +6,7 @@ class AccountFollowController < ApplicationController
   before_action :authenticate_user!
 
   def create
-    FollowService.new.call(current_user.account, @account.acct)
+    FollowService.new.call(current_user.account, @account, with_rate_limit: true)
     redirect_to account_path(@account)
   end
 end
diff --git a/app/controllers/admin/site_uploads_controller.rb b/app/controllers/admin/site_uploads_controller.rb
new file mode 100644
index 000000000..cacecedb0
--- /dev/null
+++ b/app/controllers/admin/site_uploads_controller.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module Admin
+  class SiteUploadsController < BaseController
+    before_action :set_site_upload
+
+    def destroy
+      authorize :settings, :destroy?
+
+      @site_upload.destroy!
+
+      redirect_to edit_admin_settings_path, notice: I18n.t('admin.site_uploads.destroyed_msg')
+    end
+
+    private
+
+    def set_site_upload
+      @site_upload = SiteUpload.find(params[:id])
+    end
+  end
+end
diff --git a/app/controllers/api/base_controller.rb b/app/controllers/api/base_controller.rb
index 68bf425f4..153ade253 100644
--- a/app/controllers/api/base_controller.rb
+++ b/app/controllers/api/base_controller.rb
@@ -44,6 +44,10 @@ class Api::BaseController < ApplicationController
     render json: { error: 'There was a temporary problem serving your request, please try again' }, status: 503
   end
 
+  rescue_from Mastodon::RateLimitExceededError do
+    render json: { error: I18n.t('errors.429') }, status: 429
+  end
+
   rescue_from ActionController::ParameterMissing do |e|
     render json: { error: e.to_s }, status: 400
   end
diff --git a/app/controllers/api/v1/accounts/follower_accounts_controller.rb b/app/controllers/api/v1/accounts/follower_accounts_controller.rb
index e360b8a92..850702cca 100644
--- a/app/controllers/api/v1/accounts/follower_accounts_controller.rb
+++ b/app/controllers/api/v1/accounts/follower_accounts_controller.rb
@@ -5,8 +5,6 @@ class Api::V1::Accounts::FollowerAccountsController < Api::BaseController
   before_action :set_account
   after_action :insert_pagination_headers
 
-  respond_to :json
-
   def index
     @accounts = load_accounts
     render json: @accounts, each_serializer: REST::AccountSerializer
diff --git a/app/controllers/api/v1/accounts/following_accounts_controller.rb b/app/controllers/api/v1/accounts/following_accounts_controller.rb
index a405b365f..830dcd8a1 100644
--- a/app/controllers/api/v1/accounts/following_accounts_controller.rb
+++ b/app/controllers/api/v1/accounts/following_accounts_controller.rb
@@ -5,8 +5,6 @@ class Api::V1::Accounts::FollowingAccountsController < Api::BaseController
   before_action :set_account
   after_action :insert_pagination_headers
 
-  respond_to :json
-
   def index
     @accounts = load_accounts
     render json: @accounts, each_serializer: REST::AccountSerializer
diff --git a/app/controllers/api/v1/accounts/identity_proofs_controller.rb b/app/controllers/api/v1/accounts/identity_proofs_controller.rb
index bea51ae11..8dad6fee9 100644
--- a/app/controllers/api/v1/accounts/identity_proofs_controller.rb
+++ b/app/controllers/api/v1/accounts/identity_proofs_controller.rb
@@ -4,8 +4,6 @@ class Api::V1::Accounts::IdentityProofsController < Api::BaseController
   before_action :require_user!
   before_action :set_account
 
-  respond_to :json
-
   def index
     @proofs = @account.identity_proofs.active
     render json: @proofs, each_serializer: REST::IdentityProofSerializer
diff --git a/app/controllers/api/v1/accounts/lists_controller.rb b/app/controllers/api/v1/accounts/lists_controller.rb
index 72392453c..ccb751f8f 100644
--- a/app/controllers/api/v1/accounts/lists_controller.rb
+++ b/app/controllers/api/v1/accounts/lists_controller.rb
@@ -5,8 +5,6 @@ class Api::V1::Accounts::ListsController < Api::BaseController
   before_action :require_user!
   before_action :set_account
 
-  respond_to :json
-
   def index
     @lists = @account.lists.where(account: current_account)
     render json: @lists, each_serializer: REST::ListSerializer
diff --git a/app/controllers/api/v1/accounts/pins_controller.rb b/app/controllers/api/v1/accounts/pins_controller.rb
index 0a0239c42..3915b5669 100644
--- a/app/controllers/api/v1/accounts/pins_controller.rb
+++ b/app/controllers/api/v1/accounts/pins_controller.rb
@@ -7,8 +7,6 @@ class Api::V1::Accounts::PinsController < Api::BaseController
   before_action :require_user!
   before_action :set_account
 
-  respond_to :json
-
   def create
     AccountPin.create!(account: current_account, target_account: @account)
     render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships_presenter
diff --git a/app/controllers/api/v1/accounts/relationships_controller.rb b/app/controllers/api/v1/accounts/relationships_controller.rb
index ab8a0461f..1d3992a28 100644
--- a/app/controllers/api/v1/accounts/relationships_controller.rb
+++ b/app/controllers/api/v1/accounts/relationships_controller.rb
@@ -4,8 +4,6 @@ class Api::V1::Accounts::RelationshipsController < Api::BaseController
   before_action -> { doorkeeper_authorize! :read, :'read:follows' }
   before_action :require_user!
 
-  respond_to :json
-
   def index
     accounts = Account.where(id: account_ids).select('id')
     # .where doesn't guarantee that our results are in the same order
diff --git a/app/controllers/api/v1/accounts/search_controller.rb b/app/controllers/api/v1/accounts/search_controller.rb
index 4217b527a..3061fcb7e 100644
--- a/app/controllers/api/v1/accounts/search_controller.rb
+++ b/app/controllers/api/v1/accounts/search_controller.rb
@@ -4,8 +4,6 @@ class Api::V1::Accounts::SearchController < Api::BaseController
   before_action -> { doorkeeper_authorize! :read, :'read:accounts' }
   before_action :require_user!
 
-  respond_to :json
-
   def show
     @accounts = account_search
     render json: @accounts, each_serializer: REST::AccountSerializer
diff --git a/app/controllers/api/v1/accounts/statuses_controller.rb b/app/controllers/api/v1/accounts/statuses_controller.rb
index 333db9618..114ee0a82 100644
--- a/app/controllers/api/v1/accounts/statuses_controller.rb
+++ b/app/controllers/api/v1/accounts/statuses_controller.rb
@@ -6,8 +6,6 @@ class Api::V1::Accounts::StatusesController < Api::BaseController
 
   after_action :insert_pagination_headers, unless: -> { truthy_param?(:pinned) }
 
-  respond_to :json
-
   def index
     @statuses = load_statuses
     render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
diff --git a/app/controllers/api/v1/accounts_controller.rb b/app/controllers/api/v1/accounts_controller.rb
index d68d2715f..0080faf33 100644
--- a/app/controllers/api/v1/accounts_controller.rb
+++ b/app/controllers/api/v1/accounts_controller.rb
@@ -14,7 +14,7 @@ class Api::V1::AccountsController < Api::BaseController
 
   skip_before_action :require_authenticated_user!, only: :create
 
-  respond_to :json
+  override_rate_limit_headers :follow, family: :follows
 
   def show
     render json: @account, serializer: REST::AccountSerializer
@@ -31,7 +31,7 @@ class Api::V1::AccountsController < Api::BaseController
   end
 
   def follow
-    FollowService.new.call(current_user.account, @account, reblogs: truthy_param?(:reblogs))
+    FollowService.new.call(current_user.account, @account, reblogs: truthy_param?(:reblogs), with_rate_limit: true)
 
     options = @account.locked? || current_user.account.silenced? ? {} : { following_map: { @account.id => { reblogs: truthy_param?(:reblogs) } }, requested_map: { @account.id => false } }
 
diff --git a/app/controllers/api/v1/apps/credentials_controller.rb b/app/controllers/api/v1/apps/credentials_controller.rb
index 8b63d0490..0475b2d4a 100644
--- a/app/controllers/api/v1/apps/credentials_controller.rb
+++ b/app/controllers/api/v1/apps/credentials_controller.rb
@@ -3,8 +3,6 @@
 class Api::V1::Apps::CredentialsController < Api::BaseController
   before_action -> { doorkeeper_authorize! :read }
 
-  respond_to :json
-
   def show
     render json: doorkeeper_token.application, serializer: REST::ApplicationSerializer, fields: %i(name website vapid_key)
   end
diff --git a/app/controllers/api/v1/blocks_controller.rb b/app/controllers/api/v1/blocks_controller.rb
index 4cff04cad..a2baeef90 100644
--- a/app/controllers/api/v1/blocks_controller.rb
+++ b/app/controllers/api/v1/blocks_controller.rb
@@ -5,8 +5,6 @@ class Api::V1::BlocksController < Api::BaseController
   before_action :require_user!
   after_action :insert_pagination_headers
 
-  respond_to :json
-
   def index
     @accounts = load_accounts
     render json: @accounts, each_serializer: REST::AccountSerializer
diff --git a/app/controllers/api/v1/bookmarks_controller.rb b/app/controllers/api/v1/bookmarks_controller.rb
index e1b244e76..c15212f0a 100644
--- a/app/controllers/api/v1/bookmarks_controller.rb
+++ b/app/controllers/api/v1/bookmarks_controller.rb
@@ -5,8 +5,6 @@ class Api::V1::BookmarksController < Api::BaseController
   before_action :require_user!
   after_action :insert_pagination_headers
 
-  respond_to :json
-
   def index
     @statuses = load_statuses
     render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
diff --git a/app/controllers/api/v1/conversations_controller.rb b/app/controllers/api/v1/conversations_controller.rb
index b19f27ebf..bc8013379 100644
--- a/app/controllers/api/v1/conversations_controller.rb
+++ b/app/controllers/api/v1/conversations_controller.rb
@@ -9,8 +9,6 @@ class Api::V1::ConversationsController < Api::BaseController
   before_action :set_conversation, except: :index
   after_action :insert_pagination_headers, only: :index
 
-  respond_to :json
-
   def index
     @conversations = paginated_conversations
     render json: @conversations, each_serializer: REST::ConversationSerializer
diff --git a/app/controllers/api/v1/custom_emojis_controller.rb b/app/controllers/api/v1/custom_emojis_controller.rb
index 4e6d5d7c6..08b3474cc 100644
--- a/app/controllers/api/v1/custom_emojis_controller.rb
+++ b/app/controllers/api/v1/custom_emojis_controller.rb
@@ -1,8 +1,6 @@
 # frozen_string_literal: true
 
 class Api::V1::CustomEmojisController < Api::BaseController
-  respond_to :json
-
   skip_before_action :set_cache_headers
 
   def index
diff --git a/app/controllers/api/v1/domain_blocks_controller.rb b/app/controllers/api/v1/domain_blocks_controller.rb
index af9e7a20f..5bb02d834 100644
--- a/app/controllers/api/v1/domain_blocks_controller.rb
+++ b/app/controllers/api/v1/domain_blocks_controller.rb
@@ -8,8 +8,6 @@ class Api::V1::DomainBlocksController < Api::BaseController
   before_action :require_user!
   after_action :insert_pagination_headers, only: :show
 
-  respond_to :json
-
   def show
     @blocks = load_domain_blocks
     render json: @blocks.map(&:domain)
diff --git a/app/controllers/api/v1/endorsements_controller.rb b/app/controllers/api/v1/endorsements_controller.rb
index 2770c7aef..c87dbc4ce 100644
--- a/app/controllers/api/v1/endorsements_controller.rb
+++ b/app/controllers/api/v1/endorsements_controller.rb
@@ -5,8 +5,6 @@ class Api::V1::EndorsementsController < Api::BaseController
   before_action :require_user!
   after_action :insert_pagination_headers
 
-  respond_to :json
-
   def index
     @accounts = load_accounts
     render json: @accounts, each_serializer: REST::AccountSerializer
diff --git a/app/controllers/api/v1/favourites_controller.rb b/app/controllers/api/v1/favourites_controller.rb
index db827f9d4..3e242905d 100644
--- a/app/controllers/api/v1/favourites_controller.rb
+++ b/app/controllers/api/v1/favourites_controller.rb
@@ -5,8 +5,6 @@ class Api::V1::FavouritesController < Api::BaseController
   before_action :require_user!
   after_action :insert_pagination_headers
 
-  respond_to :json
-
   def index
     @statuses = load_statuses
     render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
diff --git a/app/controllers/api/v1/featured_tags/suggestions_controller.rb b/app/controllers/api/v1/featured_tags/suggestions_controller.rb
index fb27ef88b..8c1b81a0f 100644
--- a/app/controllers/api/v1/featured_tags/suggestions_controller.rb
+++ b/app/controllers/api/v1/featured_tags/suggestions_controller.rb
@@ -2,12 +2,9 @@
 
 class Api::V1::FeaturedTags::SuggestionsController < Api::BaseController
   before_action -> { doorkeeper_authorize! :read, :'read:accounts' }, only: :index
-
   before_action :require_user!
   before_action :set_most_used_tags, only: :index
 
-  respond_to :json
-
   def index
     render json: @most_used_tags, each_serializer: REST::TagSerializer
   end
diff --git a/app/controllers/api/v1/filters_controller.rb b/app/controllers/api/v1/filters_controller.rb
index e5ebaff4d..b0ace3af0 100644
--- a/app/controllers/api/v1/filters_controller.rb
+++ b/app/controllers/api/v1/filters_controller.rb
@@ -7,8 +7,6 @@ class Api::V1::FiltersController < Api::BaseController
   before_action :set_filters, only: :index
   before_action :set_filter, only: [:show, :update, :destroy]
 
-  respond_to :json
-
   def index
     render json: @filters, each_serializer: REST::FilterSerializer
   end
diff --git a/app/controllers/api/v1/instances/activity_controller.rb b/app/controllers/api/v1/instances/activity_controller.rb
index b30e8464c..4f6b4bcbf 100644
--- a/app/controllers/api/v1/instances/activity_controller.rb
+++ b/app/controllers/api/v1/instances/activity_controller.rb
@@ -6,8 +6,6 @@ class Api::V1::Instances::ActivityController < Api::BaseController
   skip_before_action :set_cache_headers
   skip_before_action :require_authenticated_user!, unless: :whitelist_mode?
 
-  respond_to :json
-
   def show
     expires_in 1.day, public: true
     render_with_cache json: :activity, expires_in: 1.day
diff --git a/app/controllers/api/v1/instances/peers_controller.rb b/app/controllers/api/v1/instances/peers_controller.rb
index cc00d8a6b..9fa440935 100644
--- a/app/controllers/api/v1/instances/peers_controller.rb
+++ b/app/controllers/api/v1/instances/peers_controller.rb
@@ -6,8 +6,6 @@ class Api::V1::Instances::PeersController < Api::BaseController
   skip_before_action :set_cache_headers
   skip_before_action :require_authenticated_user!, unless: :whitelist_mode?
 
-  respond_to :json
-
   def index
     expires_in 1.day, public: true
     render_with_cache(expires_in: 1.day) { Account.remote.domains }
diff --git a/app/controllers/api/v1/instances_controller.rb b/app/controllers/api/v1/instances_controller.rb
index c323b60b4..5b5058a7b 100644
--- a/app/controllers/api/v1/instances_controller.rb
+++ b/app/controllers/api/v1/instances_controller.rb
@@ -1,8 +1,6 @@
 # frozen_string_literal: true
 
 class Api::V1::InstancesController < Api::BaseController
-  respond_to :json
-
   skip_before_action :set_cache_headers
   skip_before_action :require_authenticated_user!, unless: :whitelist_mode?
 
diff --git a/app/controllers/api/v1/media_controller.rb b/app/controllers/api/v1/media_controller.rb
index 81825db15..d87d7b946 100644
--- a/app/controllers/api/v1/media_controller.rb
+++ b/app/controllers/api/v1/media_controller.rb
@@ -4,8 +4,6 @@ class Api::V1::MediaController < Api::BaseController
   before_action -> { doorkeeper_authorize! :write, :'write:media' }
   before_action :require_user!
 
-  respond_to :json
-
   def create
     @media = current_account.media_attachments.create!(media_params)
     render json: @media, serializer: REST::MediaAttachmentSerializer
diff --git a/app/controllers/api/v1/mutes_controller.rb b/app/controllers/api/v1/mutes_controller.rb
index 3b3a39943..5dc047b43 100644
--- a/app/controllers/api/v1/mutes_controller.rb
+++ b/app/controllers/api/v1/mutes_controller.rb
@@ -5,8 +5,6 @@ class Api::V1::MutesController < Api::BaseController
   before_action :require_user!
   after_action :insert_pagination_headers
 
-  respond_to :json
-
   def index
     @data = @accounts = load_accounts
     render json: @accounts, each_serializer: REST::AccountSerializer
diff --git a/app/controllers/api/v1/notifications_controller.rb b/app/controllers/api/v1/notifications_controller.rb
index c91753ae7..9dce9b807 100644
--- a/app/controllers/api/v1/notifications_controller.rb
+++ b/app/controllers/api/v1/notifications_controller.rb
@@ -6,8 +6,6 @@ class Api::V1::NotificationsController < Api::BaseController
   before_action :require_user!
   after_action :insert_pagination_headers, only: :index
 
-  respond_to :json
-
   DEFAULT_NOTIFICATIONS_LIMIT = 15
 
   def index
diff --git a/app/controllers/api/v1/polls/votes_controller.rb b/app/controllers/api/v1/polls/votes_controller.rb
index 3fa0b6a76..e1d26106a 100644
--- a/app/controllers/api/v1/polls/votes_controller.rb
+++ b/app/controllers/api/v1/polls/votes_controller.rb
@@ -7,8 +7,6 @@ class Api::V1::Polls::VotesController < Api::BaseController
   before_action :require_user!
   before_action :set_poll
 
-  respond_to :json
-
   def create
     VoteService.new.call(current_account, @poll, vote_params[:choices])
     render json: @poll, serializer: REST::PollSerializer
diff --git a/app/controllers/api/v1/polls_controller.rb b/app/controllers/api/v1/polls_controller.rb
index 031e6d42d..744baf7bb 100644
--- a/app/controllers/api/v1/polls_controller.rb
+++ b/app/controllers/api/v1/polls_controller.rb
@@ -7,8 +7,6 @@ class Api::V1::PollsController < Api::BaseController
   before_action :set_poll
   before_action :refresh_poll
 
-  respond_to :json
-
   def show
     render json: @poll, serializer: REST::PollSerializer, include_results: true
   end
diff --git a/app/controllers/api/v1/preferences_controller.rb b/app/controllers/api/v1/preferences_controller.rb
index 077d39f5d..1640a8224 100644
--- a/app/controllers/api/v1/preferences_controller.rb
+++ b/app/controllers/api/v1/preferences_controller.rb
@@ -4,8 +4,6 @@ class Api::V1::PreferencesController < Api::BaseController
   before_action -> { doorkeeper_authorize! :read, :'read:accounts' }
   before_action :require_user!
 
-  respond_to :json
-
   def index
     render json: current_account, serializer: REST::PreferencesSerializer
   end
diff --git a/app/controllers/api/v1/reports_controller.rb b/app/controllers/api/v1/reports_controller.rb
index 1b0b4b05b..66c40f6f4 100644
--- a/app/controllers/api/v1/reports_controller.rb
+++ b/app/controllers/api/v1/reports_controller.rb
@@ -4,8 +4,6 @@ class Api::V1::ReportsController < Api::BaseController
   before_action -> { doorkeeper_authorize! :write, :'write:reports' }, only: [:create]
   before_action :require_user!
 
-  respond_to :json
-
   def create
     @report = ReportService.new.call(
       current_account,
diff --git a/app/controllers/api/v1/statuses/bookmarks_controller.rb b/app/controllers/api/v1/statuses/bookmarks_controller.rb
index a7f1eed00..3954af3c9 100644
--- a/app/controllers/api/v1/statuses/bookmarks_controller.rb
+++ b/app/controllers/api/v1/statuses/bookmarks_controller.rb
@@ -7,8 +7,6 @@ class Api::V1::Statuses::BookmarksController < Api::BaseController
   before_action :require_user!
   before_action :set_status
 
-  respond_to :json
-
   def create
     current_account.bookmarks.find_or_create_by!(account: current_account, status: @status)
     render json: @status, serializer: REST::StatusSerializer
diff --git a/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb b/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb
index 05f4acc33..8229786d6 100644
--- a/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb
+++ b/app/controllers/api/v1/statuses/favourited_by_accounts_controller.rb
@@ -7,8 +7,6 @@ class Api::V1::Statuses::FavouritedByAccountsController < Api::BaseController
   before_action :set_status
   after_action :insert_pagination_headers
 
-  respond_to :json
-
   def index
     @accounts = load_accounts
     render json: @accounts, each_serializer: REST::AccountSerializer
diff --git a/app/controllers/api/v1/statuses/favourites_controller.rb b/app/controllers/api/v1/statuses/favourites_controller.rb
index f18ace996..7afa822ed 100644
--- a/app/controllers/api/v1/statuses/favourites_controller.rb
+++ b/app/controllers/api/v1/statuses/favourites_controller.rb
@@ -7,8 +7,6 @@ class Api::V1::Statuses::FavouritesController < Api::BaseController
   before_action :require_user!
   before_action :set_status
 
-  respond_to :json
-
   def create
     FavouriteService.new.call(current_account, @status)
     render json: @status, serializer: REST::StatusSerializer
diff --git a/app/controllers/api/v1/statuses/mutes_controller.rb b/app/controllers/api/v1/statuses/mutes_controller.rb
index b02469b4f..43c7a525a 100644
--- a/app/controllers/api/v1/statuses/mutes_controller.rb
+++ b/app/controllers/api/v1/statuses/mutes_controller.rb
@@ -8,8 +8,6 @@ class Api::V1::Statuses::MutesController < Api::BaseController
   before_action :set_status
   before_action :set_conversation
 
-  respond_to :json
-
   def create
     current_account.mute_conversation!(@conversation)
     @mutes_map = { @conversation.id => true }
diff --git a/app/controllers/api/v1/statuses/pins_controller.rb b/app/controllers/api/v1/statuses/pins_controller.rb
index 4118a8ce4..51b1621b6 100644
--- a/app/controllers/api/v1/statuses/pins_controller.rb
+++ b/app/controllers/api/v1/statuses/pins_controller.rb
@@ -7,8 +7,6 @@ class Api::V1::Statuses::PinsController < Api::BaseController
   before_action :require_user!
   before_action :set_status
 
-  respond_to :json
-
   def create
     StatusPin.create!(account: current_account, status: @status)
     distribute_add_activity!
diff --git a/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb b/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb
index fa60e7d84..6c9e49d90 100644
--- a/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb
+++ b/app/controllers/api/v1/statuses/reblogged_by_accounts_controller.rb
@@ -7,8 +7,6 @@ class Api::V1::Statuses::RebloggedByAccountsController < Api::BaseController
   before_action :set_status
   after_action :insert_pagination_headers
 
-  respond_to :json
-
   def index
     @accounts = load_accounts
     render json: @accounts, each_serializer: REST::AccountSerializer
diff --git a/app/controllers/api/v1/statuses/reblogs_controller.rb b/app/controllers/api/v1/statuses/reblogs_controller.rb
index 67106ccbe..7fa774a4d 100644
--- a/app/controllers/api/v1/statuses/reblogs_controller.rb
+++ b/app/controllers/api/v1/statuses/reblogs_controller.rb
@@ -7,10 +7,11 @@ class Api::V1::Statuses::ReblogsController < Api::BaseController
   before_action :require_user!
   before_action :set_reblog
 
-  respond_to :json
+  override_rate_limit_headers :create, family: :statuses
 
   def create
     @status = ReblogService.new.call(current_account, @reblog, reblog_params)
+
     render json: @status, serializer: REST::StatusSerializer
   end
 
diff --git a/app/controllers/api/v1/statuses_controller.rb b/app/controllers/api/v1/statuses_controller.rb
index 486004f9c..544e8e3c9 100644
--- a/app/controllers/api/v1/statuses_controller.rb
+++ b/app/controllers/api/v1/statuses_controller.rb
@@ -8,7 +8,7 @@ class Api::V1::StatusesController < Api::BaseController
   before_action :require_user!, except:  [:show, :context]
   before_action :set_status, only:       [:show, :context]
 
-  respond_to :json
+  override_rate_limit_headers :create, family: :statuses
 
   # This API was originally unlimited, pagination cannot be introduced without
   # breaking backwards-compatibility. Arbitrarily high number to cover most
@@ -45,7 +45,8 @@ class Api::V1::StatusesController < Api::BaseController
                                          application: doorkeeper_token.application,
                                          poll: status_params[:poll],
                                          content_type: status_params[:content_type],
-                                         idempotency: request.headers['Idempotency-Key'])
+                                         idempotency: request.headers['Idempotency-Key'],
+                                         with_rate_limit: true)
 
     render json: @status, serializer: @status.is_a?(ScheduledStatus) ? REST::ScheduledStatusSerializer : REST::StatusSerializer
   end
diff --git a/app/controllers/api/v1/streaming_controller.rb b/app/controllers/api/v1/streaming_controller.rb
index ebb17608c..7cd60615a 100644
--- a/app/controllers/api/v1/streaming_controller.rb
+++ b/app/controllers/api/v1/streaming_controller.rb
@@ -1,8 +1,6 @@
 # frozen_string_literal: true
 
 class Api::V1::StreamingController < Api::BaseController
-  respond_to :json
-
   def index
     if Rails.configuration.x.streaming_api_base_url != request.host
       redirect_to streaming_api_url, status: 301
diff --git a/app/controllers/api/v1/suggestions_controller.rb b/app/controllers/api/v1/suggestions_controller.rb
index 9da2b60ae..52054160d 100644
--- a/app/controllers/api/v1/suggestions_controller.rb
+++ b/app/controllers/api/v1/suggestions_controller.rb
@@ -7,8 +7,6 @@ class Api::V1::SuggestionsController < Api::BaseController
   before_action :require_user!
   before_action :set_accounts
 
-  respond_to :json
-
   def index
     render json: @accounts, each_serializer: REST::AccountSerializer
   end
diff --git a/app/controllers/api/v1/timelines/home_controller.rb b/app/controllers/api/v1/timelines/home_controller.rb
index ff5ede138..ae6dbcb8b 100644
--- a/app/controllers/api/v1/timelines/home_controller.rb
+++ b/app/controllers/api/v1/timelines/home_controller.rb
@@ -5,8 +5,6 @@ class Api::V1::Timelines::HomeController < Api::BaseController
   before_action :require_user!, only: [:show]
   after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
 
-  respond_to :json
-
   def show
     @statuses = load_statuses
 
diff --git a/app/controllers/api/v1/timelines/public_controller.rb b/app/controllers/api/v1/timelines/public_controller.rb
index ccc10f966..581befef1 100644
--- a/app/controllers/api/v1/timelines/public_controller.rb
+++ b/app/controllers/api/v1/timelines/public_controller.rb
@@ -4,8 +4,6 @@ class Api::V1::Timelines::PublicController < Api::BaseController
   before_action :require_user!, only: [:show], if: :require_auth?
   after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
 
-  respond_to :json
-
   def show
     @statuses = load_statuses
     render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
diff --git a/app/controllers/api/v1/timelines/tag_controller.rb b/app/controllers/api/v1/timelines/tag_controller.rb
index 9adc4ad29..2d6ad5a80 100644
--- a/app/controllers/api/v1/timelines/tag_controller.rb
+++ b/app/controllers/api/v1/timelines/tag_controller.rb
@@ -4,8 +4,6 @@ class Api::V1::Timelines::TagController < Api::BaseController
   before_action :load_tag
   after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
 
-  respond_to :json
-
   def show
     @statuses = load_statuses
     render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
diff --git a/app/controllers/api/v1/trends_controller.rb b/app/controllers/api/v1/trends_controller.rb
index bcea9857e..c875e9041 100644
--- a/app/controllers/api/v1/trends_controller.rb
+++ b/app/controllers/api/v1/trends_controller.rb
@@ -3,8 +3,6 @@
 class Api::V1::TrendsController < Api::BaseController
   before_action :set_tags
 
-  respond_to :json
-
   def index
     render json: @tags, each_serializer: REST::TagSerializer
   end
diff --git a/app/controllers/api/v2/search_controller.rb b/app/controllers/api/v2/search_controller.rb
index 76decdb25..ddcf92200 100644
--- a/app/controllers/api/v2/search_controller.rb
+++ b/app/controllers/api/v2/search_controller.rb
@@ -8,8 +8,6 @@ class Api::V2::SearchController < Api::BaseController
   before_action -> { doorkeeper_authorize! :read, :'read:search' }
   before_action :require_user!
 
-  respond_to :json
-
   def index
     @search = Search.new(search_results)
     render json: @search, serializer: REST::SearchSerializer
diff --git a/app/controllers/api/web/embeds_controller.rb b/app/controllers/api/web/embeds_controller.rb
index 4aa31695c..741ba910f 100644
--- a/app/controllers/api/web/embeds_controller.rb
+++ b/app/controllers/api/web/embeds_controller.rb
@@ -1,8 +1,6 @@
 # frozen_string_literal: true
 
 class Api::Web::EmbedsController < Api::Web::BaseController
-  respond_to :json
-
   before_action :require_user!
 
   def create
diff --git a/app/controllers/api/web/push_subscriptions_controller.rb b/app/controllers/api/web/push_subscriptions_controller.rb
index f388b17e5..7916b82fa 100644
--- a/app/controllers/api/web/push_subscriptions_controller.rb
+++ b/app/controllers/api/web/push_subscriptions_controller.rb
@@ -1,8 +1,6 @@
 # frozen_string_literal: true
 
 class Api::Web::PushSubscriptionsController < Api::Web::BaseController
-  respond_to :json
-
   before_action :require_user!
 
   def create
diff --git a/app/controllers/api/web/settings_controller.rb b/app/controllers/api/web/settings_controller.rb
index e3178bf48..3d65e46ed 100644
--- a/app/controllers/api/web/settings_controller.rb
+++ b/app/controllers/api/web/settings_controller.rb
@@ -1,8 +1,6 @@
 # frozen_string_literal: true
 
 class Api::Web::SettingsController < Api::Web::BaseController
-  respond_to :json
-
   before_action :require_user!
 
   def update
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index c882d40ab..63d9f91fb 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -30,6 +30,7 @@ class ApplicationController < ActionController::Base
   rescue_from Mastodon::NotPermittedError, with: :forbidden
   rescue_from HTTP::Error, OpenSSL::SSL::SSLError, with: :internal_server_error
   rescue_from Mastodon::RaceConditionError, with: :service_unavailable
+  rescue_from Mastodon::RateLimitExceededError, with: :too_many_requests
 
   before_action :store_current_location, except: :raise_not_found, unless: :devise_controller?
   before_action :require_functional!, if: :user_signed_in?
@@ -181,6 +182,10 @@ class ApplicationController < ActionController::Base
     respond_with_error(503)
   end
 
+  def too_many_requests
+    respond_with_error(429)
+  end
+
   def single_user_mode?
     @single_user_mode ||= Rails.configuration.x.single_user_mode && Account.where('id > 0').exists?
   end
diff --git a/app/controllers/authorize_interactions_controller.rb b/app/controllers/authorize_interactions_controller.rb
index 20b3fa94b..f0bcac75b 100644
--- a/app/controllers/authorize_interactions_controller.rb
+++ b/app/controllers/authorize_interactions_controller.rb
@@ -21,7 +21,7 @@ class AuthorizeInteractionsController < ApplicationController
   end
 
   def create
-    if @resource.is_a?(Account) && FollowService.new.call(current_account, @resource)
+    if @resource.is_a?(Account) && FollowService.new.call(current_account, @resource, with_rate_limit: true)
       render :success
     else
       render :error
diff --git a/app/controllers/concerns/rate_limit_headers.rb b/app/controllers/concerns/rate_limit_headers.rb
index b79c558d8..86fe58a71 100644
--- a/app/controllers/concerns/rate_limit_headers.rb
+++ b/app/controllers/concerns/rate_limit_headers.rb
@@ -3,6 +3,20 @@
 module RateLimitHeaders
   extend ActiveSupport::Concern
 
+  class_methods do
+    def override_rate_limit_headers(method_name, options = {})
+      around_action(only: method_name, if: :current_account) do |_controller, block|
+        begin
+          block.call
+        ensure
+          rate_limiter = RateLimiter.new(current_account, options)
+          rate_limit_headers = rate_limiter.to_headers
+          response.headers.merge!(rate_limit_headers) unless response.headers['X-RateLimit-Remaining'].present? && rate_limit_headers['X-RateLimit-Remaining'].to_i > response.headers['X-RateLimit-Remaining'].to_i
+        end
+      end
+    end
+  end
+
   included do
     before_action :set_rate_limit_headers, if: :rate_limited_request?
   end
@@ -44,7 +58,7 @@ module RateLimitHeaders
   end
 
   def api_throttle_data
-    most_limited_type, = request.env['rack.attack.throttle_data'].min_by { |_, v| v[:limit] }
+    most_limited_type, = request.env['rack.attack.throttle_data'].min_by { |_, v| v[:limit] - v[:count] }
     request.env['rack.attack.throttle_data'][most_limited_type]
   end