Fix anonymous access to outbox not being cached by the reverse proxy (#16458)

* Fix anonymous access to outbox not being cached by the reverse proxy

Up until now, anonymous access to outbox was marked as public, but with a
0 duration for caching, which means remote proxies would only serve from cache
when the server was completely overwhelmed.

Changed that cache duration to one minute, so that repeated anonymous access
to one account's outbox can be appropriately cached.

Also added `Signature` to the `Vary` header in case a page is requested, so
that authenticated fetches are never served from cache (which only contains
public toots).

* Remove Vary: Accept header from webfinger controller

Indeed, we have stopped returning xrd, and only ever return jrd, so the
Accept request header does not matter anymore.

* Cache negative webfinger hits for 3 minutes
This commit is contained in:
Claire 2021-07-03 21:13:47 +02:00 committed by GitHub
parent 38b3419950
commit 49219508bc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 27 additions and 6 deletions

View file

@ -11,7 +11,11 @@ class ActivityPub::OutboxesController < ActivityPub::BaseController
before_action :set_cache_headers before_action :set_cache_headers
def show def show
expires_in(page_requested? ? 0 : 3.minutes, public: public_fetch_mode? && !(signed_request_account.present? && page_requested?)) if page_requested?
expires_in(1.minute, public: public_fetch_mode? && signed_request_account.nil?)
else
expires_in(3.minutes, public: public_fetch_mode?)
end
render json: outbox_presenter, serializer: ActivityPub::OutboxSerializer, adapter: ActivityPub::Adapter, content_type: 'application/activity+json' render json: outbox_presenter, serializer: ActivityPub::OutboxSerializer, adapter: ActivityPub::Adapter, content_type: 'application/activity+json'
end end
@ -76,4 +80,8 @@ class ActivityPub::OutboxesController < ActivityPub::BaseController
def set_account def set_account
@account = params[:account_username].present? ? Account.find_local!(username_param) : Account.representative @account = params[:account_username].present? ? Account.find_local!(username_param) : Account.representative
end end
def set_cache_headers
response.headers['Vary'] = 'Signature' if authorized_fetch_mode? || page_requested?
end
end end

View file

@ -4,7 +4,6 @@ module WellKnown
class WebfingerController < ActionController::Base class WebfingerController < ActionController::Base
include RoutingHelper include RoutingHelper
before_action { response.headers['Vary'] = 'Accept' }
before_action :set_account before_action :set_account
before_action :check_account_suspension before_action :check_account_suspension
@ -39,10 +38,12 @@ module WellKnown
end end
def bad_request def bad_request
expires_in(3.minutes, public: true)
head 400 head 400
end end
def not_found def not_found
expires_in(3.minutes, public: true)
head 404 head 404
end end

View file

@ -55,6 +55,10 @@ RSpec.describe ActivityPub::OutboxesController, type: :controller do
it_behaves_like 'cachable response' it_behaves_like 'cachable response'
it 'does not have a Vary header' do
expect(response.headers['Vary']).to be_nil
end
context 'when account is permanently suspended' do context 'when account is permanently suspended' do
before do before do
account.suspend! account.suspend!
@ -96,6 +100,10 @@ RSpec.describe ActivityPub::OutboxesController, type: :controller do
it_behaves_like 'cachable response' it_behaves_like 'cachable response'
it 'returns Vary header with Signature' do
expect(response.headers['Vary']).to include 'Signature'
end
context 'when account is permanently suspended' do context 'when account is permanently suspended' do
before do before do
account.suspend! account.suspend!
@ -144,7 +152,7 @@ RSpec.describe ActivityPub::OutboxesController, type: :controller do
end end
it 'returns private Cache-Control header' do it 'returns private Cache-Control header' do
expect(response.headers['Cache-Control']).to eq 'max-age=0, private' expect(response.headers['Cache-Control']).to eq 'max-age=60, private'
end end
end end
@ -170,7 +178,7 @@ RSpec.describe ActivityPub::OutboxesController, type: :controller do
end end
it 'returns private Cache-Control header' do it 'returns private Cache-Control header' do
expect(response.headers['Cache-Control']).to eq 'max-age=0, private' expect(response.headers['Cache-Control']).to eq 'max-age=60, private'
end end
end end
@ -195,7 +203,7 @@ RSpec.describe ActivityPub::OutboxesController, type: :controller do
end end
it 'returns private Cache-Control header' do it 'returns private Cache-Control header' do
expect(response.headers['Cache-Control']).to eq 'max-age=0, private' expect(response.headers['Cache-Control']).to eq 'max-age=60, private'
end end
end end
@ -220,7 +228,7 @@ RSpec.describe ActivityPub::OutboxesController, type: :controller do
end end
it 'returns private Cache-Control header' do it 'returns private Cache-Control header' do
expect(response.headers['Cache-Control']).to eq 'max-age=0, private' expect(response.headers['Cache-Control']).to eq 'max-age=60, private'
end end
end end
end end

View file

@ -24,6 +24,10 @@ describe WellKnown::WebfingerController, type: :controller do
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
end end
it 'does not set a Vary header' do
expect(response.headers['Vary']).to be_nil
end
it 'returns application/jrd+json' do it 'returns application/jrd+json' do
expect(response.media_type).to eq 'application/jrd+json' expect(response.media_type).to eq 'application/jrd+json'
end end