]> cat aescling's git repositories - mastodon.git/commitdiff
Cache JSON of immutable ActivityPub representations (#6171)
authorEugen Rochko <eugen@zeonfederated.com>
Thu, 4 Jan 2018 00:21:38 +0000 (01:21 +0100)
committerGitHub <noreply@github.com>
Thu, 4 Jan 2018 00:21:38 +0000 (01:21 +0100)
app/controllers/accounts_controller.rb
app/controllers/activitypub/follows_controller.rb
app/controllers/application_controller.rb
app/controllers/emojis_controller.rb
app/controllers/statuses_controller.rb

index 75915b33712f626d36b05dccd0f9b6a6e1e8ad23..69fd20e27f4a55e0c5d6795046bffd65ecdb17a9 100644 (file)
@@ -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
index 8b1cddeb4d096028ddbc31da626ea3f8417f5460..038bcbabc2d880afd53a632c81e5c862b88b4c27 100644 (file)
@@ -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
index 51a978f440a3a63879fa7ba07ac2fae59c53dd0a..e17d1f26e3e96d84848a349d292846349491c3de 100644 (file)
@@ -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
index a82b9340bf83ae3cea1439245ce92148fab43d7d..c9725ccc0d2d26a384a84dd4ed06e72050eb37d2 100644 (file)
@@ -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
index c00b9f034e55ce85c065ccb686bde89c1986c54a..1a440fd5997030bc23c2ccd67ac2d7a6c7c0d19b 100644 (file)
@@ -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