about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEugen Rochko <eugen@zeonfederated.com>2018-01-04 01:21:38 +0100
committerGitHub <noreply@github.com>2018-01-04 01:21:38 +0100
commitc10f4bdb037d87444a76e52e85f046e7e59d753a (patch)
tree52298920f6f4bae47bf6ef5f23f1d43b7e4d0997
parentd907d4352e9b6cb22bc1fabd42ca3fc60aef8a37 (diff)
Cache JSON of immutable ActivityPub representations (#6171)
-rw-r--r--app/controllers/accounts_controller.rb12
-rw-r--r--app/controllers/activitypub/follows_controller.rb22
-rw-r--r--app/controllers/application_controller.rb14
-rw-r--r--app/controllers/emojis_controller.rb10
-rw-r--r--app/controllers/statuses_controller.rb24
5 files changed, 49 insertions, 33 deletions
diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb
index 75915b337..69fd20e27 100644
--- a/app/controllers/accounts_controller.rb
+++ b/app/controllers/accounts_controller.rb
@@ -2,7 +2,8 @@
 
 class AccountsController < ApplicationController
   include AccountControllerConcern
-  include SignatureVerification
+
+  before_action :set_cache_headers
 
   def show
     respond_to do |format|
@@ -26,10 +27,11 @@ class AccountsController < ApplicationController
       end
 
       format.json do
-        render json: @account,
-               serializer: ActivityPub::ActorSerializer,
-               adapter: ActivityPub::Adapter,
-               content_type: 'application/activity+json'
+        skip_session!
+
+        render_cached_json(['activitypub', 'actor', @account.cache_key], content_type: 'application/activity+json') do
+          ActiveModelSerializers::SerializableResource.new(@account, serializer: ActivityPub::ActorSerializer, adapter: ActivityPub::Adapter)
+        end
       end
     end
   end
diff --git a/app/controllers/activitypub/follows_controller.rb b/app/controllers/activitypub/follows_controller.rb
index 8b1cddeb4..038bcbabc 100644
--- a/app/controllers/activitypub/follows_controller.rb
+++ b/app/controllers/activitypub/follows_controller.rb
@@ -4,15 +4,19 @@ class ActivityPub::FollowsController < Api::BaseController
   include SignatureVerification
 
   def show
-    render(
-      json: FollowRequest.includes(:account).references(:account).find_by!(
-        id: params.require(:id),
-        accounts: { domain: nil, username: params.require(:account_username) },
-        target_account: signed_request_account
-      ),
-      serializer: ActivityPub::FollowSerializer,
-      adapter: ActivityPub::Adapter,
-      content_type: 'application/activity+json'
+    render json: follow_request,
+           serializer: ActivityPub::FollowSerializer,
+           adapter: ActivityPub::Adapter,
+           content_type: 'application/activity+json'
+  end
+
+  private
+
+  def follow_request
+    FollowRequest.includes(:account).references(:account).find_by!(
+      id: params.require(:id),
+      accounts: { domain: nil, username: params.require(:account_username) },
+      target_account: signed_request_account
     )
   end
 end
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 51a978f44..e17d1f26e 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -123,11 +123,23 @@ class ApplicationController < ActionController::Base
   end
 
   def render_cached_json(cache_key, **options)
+    options[:expires_in] ||= 3.minutes
+    cache_key              = cache_key.join(':') if cache_key.is_a?(Enumerable)
+    content_type           = options.delete(:content_type) || 'application/json'
+
     data = Rails.cache.fetch(cache_key, { raw: true }.merge(options)) do
       yield.to_json
     end
 
     expires_in options[:expires_in], public: true
-    render json: data
+    render json: data, content_type: content_type
+  end
+
+  def set_cache_headers
+    response.headers['Vary'] = 'Accept'
+  end
+
+  def skip_session!
+    request.session_options[:skip] = true
   end
 end
diff --git a/app/controllers/emojis_controller.rb b/app/controllers/emojis_controller.rb
index a82b9340b..c9725ccc0 100644
--- a/app/controllers/emojis_controller.rb
+++ b/app/controllers/emojis_controller.rb
@@ -2,14 +2,16 @@
 
 class EmojisController < ApplicationController
   before_action :set_emoji
+  before_action :set_cache_headers
 
   def show
     respond_to do |format|
       format.json do
-        render json: @emoji,
-               serializer: ActivityPub::EmojiSerializer,
-               adapter: ActivityPub::Adapter,
-               content_type: 'application/activity+json'
+        skip_session!
+
+        render_cached_json(['activitypub', 'emoji', @emoji.cache_key], content_type: 'application/activity+json') do
+          ActiveModelSerializers::SerializableResource.new(@emoji, serializer: ActivityPub::EmojiSerializer, adapter: ActivityPub::Adapter)
+        end
       end
     end
   end
diff --git a/app/controllers/statuses_controller.rb b/app/controllers/statuses_controller.rb
index c00b9f034..1a440fd59 100644
--- a/app/controllers/statuses_controller.rb
+++ b/app/controllers/statuses_controller.rb
@@ -10,7 +10,7 @@ class StatusesController < ApplicationController
   before_action :set_link_headers
   before_action :check_account_suspension
   before_action :redirect_to_original, only: [:show]
-  before_action { response.headers['Vary'] = 'Accept' }
+  before_action :set_cache_headers
 
   def show
     respond_to do |format|
@@ -22,25 +22,21 @@ class StatusesController < ApplicationController
       end
 
       format.json do
-        render json: @status,
-               serializer: ActivityPub::NoteSerializer,
-               adapter: ActivityPub::Adapter,
-               content_type: 'application/activity+json'
-
-        # Allow HTTP caching for 3 minutes if the status is public
-        unless @stream_entry.hidden?
-          request.session_options[:skip] = true
-          expires_in(3.minutes, public: true)
+        skip_session! unless @stream_entry.hidden?
+
+        render_cached_json(['activitypub', 'note', @status.cache_key], content_type: 'application/activity+json') do
+          ActiveModelSerializers::SerializableResource.new(@status, serializer: ActivityPub::NoteSerializer, adapter: ActivityPub::Adapter)
         end
       end
     end
   end
 
   def activity
-    render json: @status,
-           serializer: ActivityPub::ActivitySerializer,
-           adapter: ActivityPub::Adapter,
-           content_type: 'application/activity+json'
+    skip_session!
+
+    render_cached_json(['activitypub', 'activity', @status.cache_key], content_type: 'application/activity+json') do
+      ActiveModelSerializers::SerializableResource.new(@status, serializer: ActivityPub::ActivitySerializer, adapter: ActivityPub::Adapter)
+    end
   end
 
   def embed