Change unauthenticated responses to be cached in REST API (#24348)
This commit is contained in:
parent
d94f500d9c
commit
b61ff36351
29 changed files with 67 additions and 9 deletions
|
@ -6,6 +6,7 @@ class Api::BaseController < ApplicationController
|
||||||
|
|
||||||
include RateLimitHeaders
|
include RateLimitHeaders
|
||||||
include AccessTokenTrackingConcern
|
include AccessTokenTrackingConcern
|
||||||
|
include ApiCachingConcern
|
||||||
|
|
||||||
skip_before_action :store_current_location
|
skip_before_action :store_current_location
|
||||||
skip_before_action :require_functional!, unless: :whitelist_mode?
|
skip_before_action :require_functional!, unless: :whitelist_mode?
|
||||||
|
@ -13,6 +14,8 @@ class Api::BaseController < ApplicationController
|
||||||
before_action :require_authenticated_user!, if: :disallow_unauthenticated_api_access?
|
before_action :require_authenticated_user!, if: :disallow_unauthenticated_api_access?
|
||||||
before_action :require_not_suspended!
|
before_action :require_not_suspended!
|
||||||
|
|
||||||
|
vary_by 'Authorization'
|
||||||
|
|
||||||
protect_from_forgery with: :null_session
|
protect_from_forgery with: :null_session
|
||||||
|
|
||||||
content_security_policy do |p|
|
content_security_policy do |p|
|
||||||
|
|
|
@ -6,6 +6,7 @@ class Api::V1::Accounts::FollowerAccountsController < Api::BaseController
|
||||||
after_action :insert_pagination_headers
|
after_action :insert_pagination_headers
|
||||||
|
|
||||||
def index
|
def index
|
||||||
|
cache_if_unauthenticated!
|
||||||
@accounts = load_accounts
|
@accounts = load_accounts
|
||||||
render json: @accounts, each_serializer: REST::AccountSerializer
|
render json: @accounts, each_serializer: REST::AccountSerializer
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,6 +6,7 @@ class Api::V1::Accounts::FollowingAccountsController < Api::BaseController
|
||||||
after_action :insert_pagination_headers
|
after_action :insert_pagination_headers
|
||||||
|
|
||||||
def index
|
def index
|
||||||
|
cache_if_unauthenticated!
|
||||||
@accounts = load_accounts
|
@accounts = load_accounts
|
||||||
render json: @accounts, each_serializer: REST::AccountSerializer
|
render json: @accounts, each_serializer: REST::AccountSerializer
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,6 +5,7 @@ class Api::V1::Accounts::LookupController < Api::BaseController
|
||||||
before_action :set_account
|
before_action :set_account
|
||||||
|
|
||||||
def show
|
def show
|
||||||
|
cache_if_unauthenticated!
|
||||||
render json: @account, serializer: REST::AccountSerializer
|
render json: @account, serializer: REST::AccountSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ class Api::V1::Accounts::StatusesController < Api::BaseController
|
||||||
after_action :insert_pagination_headers, unless: -> { truthy_param?(:pinned) }
|
after_action :insert_pagination_headers, unless: -> { truthy_param?(:pinned) }
|
||||||
|
|
||||||
def index
|
def index
|
||||||
|
cache_if_unauthenticated!
|
||||||
@statuses = load_statuses
|
@statuses = load_statuses
|
||||||
render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
|
render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
|
||||||
end
|
end
|
||||||
|
|
|
@ -18,6 +18,7 @@ class Api::V1::AccountsController < Api::BaseController
|
||||||
override_rate_limit_headers :follow, family: :follows
|
override_rate_limit_headers :follow, family: :follows
|
||||||
|
|
||||||
def show
|
def show
|
||||||
|
cache_if_unauthenticated!
|
||||||
render json: @account, serializer: REST::AccountSerializer
|
render json: @account, serializer: REST::AccountSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Api::V1::CustomEmojisController < Api::BaseController
|
class Api::V1::CustomEmojisController < Api::BaseController
|
||||||
|
vary_by ''
|
||||||
|
|
||||||
def index
|
def index
|
||||||
expires_in 3.minutes, public: true
|
cache_even_if_authenticated!
|
||||||
render_with_cache(each_serializer: REST::CustomEmojiSerializer) { CustomEmoji.listed.includes(:category) }
|
render_with_cache(each_serializer: REST::CustomEmojiSerializer) { CustomEmoji.listed.includes(:category) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,6 +5,7 @@ class Api::V1::DirectoriesController < Api::BaseController
|
||||||
before_action :set_accounts
|
before_action :set_accounts
|
||||||
|
|
||||||
def show
|
def show
|
||||||
|
cache_if_unauthenticated!
|
||||||
render json: @accounts, each_serializer: REST::AccountSerializer
|
render json: @accounts, each_serializer: REST::AccountSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,10 @@ class Api::V1::Instances::ActivityController < Api::BaseController
|
||||||
|
|
||||||
skip_before_action :require_authenticated_user!, unless: :whitelist_mode?
|
skip_before_action :require_authenticated_user!, unless: :whitelist_mode?
|
||||||
|
|
||||||
|
vary_by ''
|
||||||
|
|
||||||
def show
|
def show
|
||||||
expires_in 1.day, public: true
|
cache_even_if_authenticated!
|
||||||
render_with_cache json: :activity, expires_in: 1.day
|
render_with_cache json: :activity, expires_in: 1.day
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,10 @@ class Api::V1::Instances::DomainBlocksController < Api::BaseController
|
||||||
before_action :require_enabled_api!
|
before_action :require_enabled_api!
|
||||||
before_action :set_domain_blocks
|
before_action :set_domain_blocks
|
||||||
|
|
||||||
|
vary_by ''
|
||||||
|
|
||||||
def index
|
def index
|
||||||
expires_in 3.minutes, public: true
|
cache_even_if_authenticated!
|
||||||
render json: @domain_blocks, each_serializer: REST::DomainBlockSerializer, with_comment: (Setting.show_domain_blocks_rationale == 'all' || (Setting.show_domain_blocks_rationale == 'users' && user_signed_in?))
|
render json: @domain_blocks, each_serializer: REST::DomainBlockSerializer, with_comment: (Setting.show_domain_blocks_rationale == 'all' || (Setting.show_domain_blocks_rationale == 'users' && user_signed_in?))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,10 @@ class Api::V1::Instances::ExtendedDescriptionsController < Api::BaseController
|
||||||
|
|
||||||
before_action :set_extended_description
|
before_action :set_extended_description
|
||||||
|
|
||||||
|
vary_by ''
|
||||||
|
|
||||||
def show
|
def show
|
||||||
expires_in 3.minutes, public: true
|
cache_even_if_authenticated!
|
||||||
render json: @extended_description, serializer: REST::ExtendedDescriptionSerializer
|
render json: @extended_description, serializer: REST::ExtendedDescriptionSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,10 @@ class Api::V1::Instances::PeersController < Api::BaseController
|
||||||
|
|
||||||
skip_before_action :require_authenticated_user!, unless: :whitelist_mode?
|
skip_before_action :require_authenticated_user!, unless: :whitelist_mode?
|
||||||
|
|
||||||
|
vary_by ''
|
||||||
|
|
||||||
def index
|
def index
|
||||||
expires_in 1.day, public: true
|
cache_even_if_authenticated!
|
||||||
render_with_cache(expires_in: 1.day) { Instance.where.not(domain: DomainBlock.select(:domain)).pluck(:domain) }
|
render_with_cache(expires_in: 1.day) { Instance.where.not(domain: DomainBlock.select(:domain)).pluck(:domain) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,10 @@ class Api::V1::Instances::PrivacyPoliciesController < Api::BaseController
|
||||||
|
|
||||||
before_action :set_privacy_policy
|
before_action :set_privacy_policy
|
||||||
|
|
||||||
|
vary_by ''
|
||||||
|
|
||||||
def show
|
def show
|
||||||
expires_in 1.day, public: true
|
cache_even_if_authenticated!
|
||||||
render json: @privacy_policy, serializer: REST::PrivacyPolicySerializer
|
render json: @privacy_policy, serializer: REST::PrivacyPolicySerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,10 @@ class Api::V1::Instances::RulesController < Api::BaseController
|
||||||
|
|
||||||
before_action :set_rules
|
before_action :set_rules
|
||||||
|
|
||||||
|
vary_by ''
|
||||||
|
|
||||||
def index
|
def index
|
||||||
|
cache_even_if_authenticated!
|
||||||
render json: @rules, each_serializer: REST::RuleSerializer
|
render json: @rules, each_serializer: REST::RuleSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,10 @@ class Api::V1::Instances::TranslationLanguagesController < Api::BaseController
|
||||||
|
|
||||||
before_action :set_languages
|
before_action :set_languages
|
||||||
|
|
||||||
|
vary_by ''
|
||||||
|
|
||||||
def show
|
def show
|
||||||
expires_in 1.day, public: true
|
cache_even_if_authenticated!
|
||||||
render json: @languages
|
render json: @languages
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,10 @@
|
||||||
class Api::V1::InstancesController < Api::BaseController
|
class Api::V1::InstancesController < Api::BaseController
|
||||||
skip_before_action :require_authenticated_user!, unless: :whitelist_mode?
|
skip_before_action :require_authenticated_user!, unless: :whitelist_mode?
|
||||||
|
|
||||||
|
vary_by ''
|
||||||
|
|
||||||
def show
|
def show
|
||||||
expires_in 3.minutes, public: true
|
cache_even_if_authenticated!
|
||||||
render_with_cache json: InstancePresenter.new, serializer: REST::V1::InstanceSerializer, root: 'instance'
|
render_with_cache json: InstancePresenter.new, serializer: REST::V1::InstanceSerializer, root: 'instance'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,6 +8,7 @@ class Api::V1::PollsController < Api::BaseController
|
||||||
before_action :refresh_poll
|
before_action :refresh_poll
|
||||||
|
|
||||||
def show
|
def show
|
||||||
|
cache_if_unauthenticated!
|
||||||
render json: @poll, serializer: REST::PollSerializer, include_results: true
|
render json: @poll, serializer: REST::PollSerializer, include_results: true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ class Api::V1::Statuses::FavouritedByAccountsController < Api::BaseController
|
||||||
after_action :insert_pagination_headers
|
after_action :insert_pagination_headers
|
||||||
|
|
||||||
def index
|
def index
|
||||||
|
cache_if_unauthenticated!
|
||||||
@accounts = load_accounts
|
@accounts = load_accounts
|
||||||
render json: @accounts, each_serializer: REST::AccountSerializer
|
render json: @accounts, each_serializer: REST::AccountSerializer
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,6 +7,7 @@ class Api::V1::Statuses::HistoriesController < Api::BaseController
|
||||||
before_action :set_status
|
before_action :set_status
|
||||||
|
|
||||||
def show
|
def show
|
||||||
|
cache_if_unauthenticated!
|
||||||
render json: @status.edits.includes(:account, status: [:account]), each_serializer: REST::StatusEditSerializer
|
render json: @status.edits.includes(:account, status: [:account]), each_serializer: REST::StatusEditSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ class Api::V1::Statuses::RebloggedByAccountsController < Api::BaseController
|
||||||
after_action :insert_pagination_headers
|
after_action :insert_pagination_headers
|
||||||
|
|
||||||
def index
|
def index
|
||||||
|
cache_if_unauthenticated!
|
||||||
@accounts = load_accounts
|
@accounts = load_accounts
|
||||||
render json: @accounts, each_serializer: REST::AccountSerializer
|
render json: @accounts, each_serializer: REST::AccountSerializer
|
||||||
end
|
end
|
||||||
|
|
|
@ -24,11 +24,14 @@ class Api::V1::StatusesController < Api::BaseController
|
||||||
DESCENDANTS_DEPTH_LIMIT = 20
|
DESCENDANTS_DEPTH_LIMIT = 20
|
||||||
|
|
||||||
def show
|
def show
|
||||||
|
cache_if_unauthenticated!
|
||||||
@status = cache_collection([@status], Status).first
|
@status = cache_collection([@status], Status).first
|
||||||
render json: @status, serializer: REST::StatusSerializer
|
render json: @status, serializer: REST::StatusSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
def context
|
def context
|
||||||
|
cache_if_unauthenticated!
|
||||||
|
|
||||||
ancestors_limit = CONTEXT_LIMIT
|
ancestors_limit = CONTEXT_LIMIT
|
||||||
descendants_limit = CONTEXT_LIMIT
|
descendants_limit = CONTEXT_LIMIT
|
||||||
descendants_depth_limit = nil
|
descendants_depth_limit = nil
|
||||||
|
|
|
@ -8,6 +8,7 @@ class Api::V1::TagsController < Api::BaseController
|
||||||
override_rate_limit_headers :follow, family: :follows
|
override_rate_limit_headers :follow, family: :follows
|
||||||
|
|
||||||
def show
|
def show
|
||||||
|
cache_if_unauthenticated!
|
||||||
render json: @tag, serializer: REST::TagSerializer
|
render json: @tag, serializer: REST::TagSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ class Api::V1::Timelines::PublicController < Api::BaseController
|
||||||
after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
|
after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
|
||||||
|
|
||||||
def show
|
def show
|
||||||
|
cache_if_unauthenticated!
|
||||||
@statuses = load_statuses
|
@statuses = load_statuses
|
||||||
render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
|
render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,6 +5,7 @@ class Api::V1::Timelines::TagController < Api::BaseController
|
||||||
after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
|
after_action :insert_pagination_headers, unless: -> { @statuses.empty? }
|
||||||
|
|
||||||
def show
|
def show
|
||||||
|
cache_if_unauthenticated!
|
||||||
@statuses = load_statuses
|
@statuses = load_statuses
|
||||||
render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
|
render json: @statuses, each_serializer: REST::StatusSerializer, relationships: StatusRelationshipsPresenter.new(@statuses, current_user&.account_id)
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Api::V1::Trends::LinksController < Api::BaseController
|
class Api::V1::Trends::LinksController < Api::BaseController
|
||||||
|
vary_by 'Authorization, Accept-Language'
|
||||||
|
|
||||||
before_action :set_links
|
before_action :set_links
|
||||||
|
|
||||||
after_action :insert_pagination_headers
|
after_action :insert_pagination_headers
|
||||||
|
@ -8,6 +10,7 @@ class Api::V1::Trends::LinksController < Api::BaseController
|
||||||
DEFAULT_LINKS_LIMIT = 10
|
DEFAULT_LINKS_LIMIT = 10
|
||||||
|
|
||||||
def index
|
def index
|
||||||
|
cache_if_unauthenticated!
|
||||||
render json: @links, each_serializer: REST::Trends::LinkSerializer
|
render json: @links, each_serializer: REST::Trends::LinkSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Api::V1::Trends::StatusesController < Api::BaseController
|
class Api::V1::Trends::StatusesController < Api::BaseController
|
||||||
|
vary_by 'Authorization, Accept-Language'
|
||||||
|
|
||||||
before_action :set_statuses
|
before_action :set_statuses
|
||||||
|
|
||||||
after_action :insert_pagination_headers
|
after_action :insert_pagination_headers
|
||||||
|
|
||||||
def index
|
def index
|
||||||
|
cache_if_unauthenticated!
|
||||||
render json: @statuses, each_serializer: REST::StatusSerializer
|
render json: @statuses, each_serializer: REST::StatusSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ class Api::V1::Trends::TagsController < Api::BaseController
|
||||||
DEFAULT_TAGS_LIMIT = 10
|
DEFAULT_TAGS_LIMIT = 10
|
||||||
|
|
||||||
def index
|
def index
|
||||||
|
cache_if_unauthenticated!
|
||||||
render json: @tags, each_serializer: REST::TagSerializer, relationships: TagRelationshipsPresenter.new(@tags, current_user&.account_id)
|
render json: @tags, each_serializer: REST::TagSerializer, relationships: TagRelationshipsPresenter.new(@tags, current_user&.account_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
class Api::V2::InstancesController < Api::V1::InstancesController
|
class Api::V2::InstancesController < Api::V1::InstancesController
|
||||||
def show
|
def show
|
||||||
expires_in 3.minutes, public: true
|
cache_even_if_authenticated!
|
||||||
render_with_cache json: InstancePresenter.new, serializer: REST::InstanceSerializer, root: 'instance'
|
render_with_cache json: InstancePresenter.new, serializer: REST::InstanceSerializer, root: 'instance'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
13
app/controllers/concerns/api_caching_concern.rb
Normal file
13
app/controllers/concerns/api_caching_concern.rb
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module ApiCachingConcern
|
||||||
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
|
def cache_if_unauthenticated!
|
||||||
|
expires_in(15.seconds, public: true, stale_while_revalidate: 30.seconds, stale_if_error: 1.day) unless user_signed_in?
|
||||||
|
end
|
||||||
|
|
||||||
|
def cache_even_if_authenticated!
|
||||||
|
expires_in(5.minutes, public: true, stale_while_revalidate: 30.seconds, stale_if_error: 1.day) unless whitelist_mode?
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue