Following an ActivityRelay fails with `{:content_type, "application/json; charset=utf-8"}`
Environment
- Installation type (OTP or From Source): From Source
- Pleroma version (could be found in the "Version" tab of settings in Pleroma-FE):
2.2.50-389-g79a509ee-develop
- Elixir version (
elixir -v
for from source installations, N/A for OTP):Erlang/OTP 23 [erts-11.1.2] [source] [64-bit] [smp:2:2] [ds:2:2:10] [async-threads:1] [hipe]
,Elixir 1.11.0 (compiled with Erlang/OTP 23)
- Operating system: Arch Linux,
Linux 5.9.8-arch1-1 #1 SMP PREEMPT Tue, 10 Nov 2020 22:44:11 +0000 x86_64 GNU/Linux
- PostgreSQL version (
psql -V
):psql (PostgreSQL) 12.5
Bug description
When trying to follow and ActivityRelay instance, the pleroma.relay follow
task fails like this if the relay actor is not already present in the local database (i.e., the relay was not followed previously):
sudo -Hu pleroma MIX_ENV=prod mix pleroma.relay follow https://relay.beckmeyer.us/actor
00:12:31.714 [debug] QUERY OK source="users" db=24.5ms queue=1.8ms idle=187.1ms
SELECT u0."id", u0."bio", u0."raw_bio", u0."email", u0."name", u0."nickname", u0."password_hash", u0."keys", u0."public_key", u0."ap_id", u0."avatar", u0."local", u0."follower_address", u0."following_address", u0."tags", u0."last_refreshed_at", u0."last_digest_emailed_at", u0."banner", u0."background", u0."note_count", u0."follower_count", u0."following_count", u0."is_locked", u0."confirmation_pending", u0."password_reset_pending", u0."approval_pending", u0."registration_reason", u0."confirmation_token", u0."default_scope", u0."domain_blocks", u0."deactivated", u0."no_rich_text", u0."ap_enabled", u0."is_moderator", u0."is_admin", u0."show_role", u0."mastofe_settings", u0."uri", u0."hide_followers_count", u0."hide_follows_count", u0."hide_followers", u0."hide_follows", u0."hide_favorites", u0."pinned_activities", u0."email_notifications", u0."mascot", u0."emoji", u0."pleroma_settings_store", u0."fields", u0."raw_fields", u0."is_discoverable", u0."invisible", u0."allow_following_move", u0."skip_thread_containment", u0."actor_type", u0."also_known_as", u0."inbox", u0."shared_inbox", u0."accepts_chat_messages", u0."notification_settings", u0."blocks", u0."mutes", u0."muted_reblogs", u0."muted_notifications", u0."subscribers", u0."multi_factor_authentication_settings", u0."inserted_at", u0."updated_at" FROM "users" AS u0 WHERE (u0."ap_id" = $1) ["https://pleroma.marussy.com/relay"]
00:12:31.738 [debug] QUERY OK source="users" db=4.6ms idle=236.0ms
SELECT u0."id", u0."bio", u0."raw_bio", u0."email", u0."name", u0."nickname", u0."password_hash", u0."keys", u0."public_key", u0."ap_id", u0."avatar", u0."local", u0."follower_address", u0."following_address", u0."tags", u0."last_refreshed_at", u0."last_digest_emailed_at", u0."banner", u0."background", u0."note_count", u0."follower_count", u0."following_count", u0."is_locked", u0."confirmation_pending", u0."password_reset_pending", u0."approval_pending", u0."registration_reason", u0."confirmation_token", u0."default_scope", u0."domain_blocks", u0."deactivated", u0."no_rich_text", u0."ap_enabled", u0."is_moderator", u0."is_admin", u0."show_role", u0."mastofe_settings", u0."uri", u0."hide_followers_count", u0."hide_follows_count", u0."hide_followers", u0."hide_follows", u0."hide_favorites", u0."pinned_activities", u0."email_notifications", u0."mascot", u0."emoji", u0."pleroma_settings_store", u0."fields", u0."raw_fields", u0."is_discoverable", u0."invisible", u0."allow_following_move", u0."skip_thread_containment", u0."actor_type", u0."also_known_as", u0."inbox", u0."shared_inbox", u0."accepts_chat_messages", u0."notification_settings", u0."blocks", u0."mutes", u0."muted_reblogs", u0."muted_notifications", u0."subscribers", u0."multi_factor_authentication_settings", u0."inserted_at", u0."updated_at" FROM "users" AS u0 WHERE (u0."ap_id" = $1) ["https://relay.beckmeyer.us/actor"]
00:12:31.743 [debug] QUERY OK source="users" db=4.6ms idle=241.0ms
SELECT u0."id", u0."bio", u0."raw_bio", u0."email", u0."name", u0."nickname", u0."password_hash", u0."keys", u0."public_key", u0."ap_id", u0."avatar", u0."local", u0."follower_address", u0."following_address", u0."tags", u0."last_refreshed_at", u0."last_digest_emailed_at", u0."banner", u0."background", u0."note_count", u0."follower_count", u0."following_count", u0."is_locked", u0."confirmation_pending", u0."password_reset_pending", u0."approval_pending", u0."registration_reason", u0."confirmation_token", u0."default_scope", u0."domain_blocks", u0."deactivated", u0."no_rich_text", u0."ap_enabled", u0."is_moderator", u0."is_admin", u0."show_role", u0."mastofe_settings", u0."uri", u0."hide_followers_count", u0."hide_follows_count", u0."hide_followers", u0."hide_follows", u0."hide_favorites", u0."pinned_activities", u0."email_notifications", u0."mascot", u0."emoji", u0."pleroma_settings_store", u0."fields", u0."raw_fields", u0."is_discoverable", u0."invisible", u0."allow_following_move", u0."skip_thread_containment", u0."actor_type", u0."also_known_as", u0."inbox", u0."shared_inbox", u0."accepts_chat_messages", u0."notification_settings", u0."blocks", u0."mutes", u0."muted_reblogs", u0."muted_notifications", u0."subscribers", u0."multi_factor_authentication_settings", u0."inserted_at", u0."updated_at" FROM "users" AS u0 WHERE (u0."ap_id" = $1) ["https://relay.beckmeyer.us/actor"]
00:12:31.743 [debug] Fetching object https://relay.beckmeyer.us/actor via AP
00:12:31.838 [debug] QUERY OK source="users" db=4.9ms idle=336.4ms
SELECT u0."id", u0."bio", u0."raw_bio", u0."email", u0."name", u0."nickname", u0."password_hash", u0."keys", u0."public_key", u0."ap_id", u0."avatar", u0."local", u0."follower_address", u0."following_address", u0."tags", u0."last_refreshed_at", u0."last_digest_emailed_at", u0."banner", u0."background", u0."note_count", u0."follower_count", u0."following_count", u0."is_locked", u0."confirmation_pending", u0."password_reset_pending", u0."approval_pending", u0."registration_reason", u0."confirmation_token", u0."default_scope", u0."domain_blocks", u0."deactivated", u0."no_rich_text", u0."ap_enabled", u0."is_moderator", u0."is_admin", u0."show_role", u0."mastofe_settings", u0."uri", u0."hide_followers_count", u0."hide_follows_count", u0."hide_followers", u0."hide_follows", u0."hide_favorites", u0."pinned_activities", u0."email_notifications", u0."mascot", u0."emoji", u0."pleroma_settings_store", u0."fields", u0."raw_fields", u0."is_discoverable", u0."invisible", u0."allow_following_move", u0."skip_thread_containment", u0."actor_type", u0."also_known_as", u0."inbox", u0."shared_inbox", u0."accepts_chat_messages", u0."notification_settings", u0."blocks", u0."mutes", u0."muted_reblogs", u0."muted_notifications", u0."subscribers", u0."multi_factor_authentication_settings", u0."inserted_at", u0."updated_at" FROM "users" AS u0 WHERE (u0."ap_id" = $1) ["https://pleroma.marussy.com/internal/fetch"]
00:12:33.539 [error] Could not decode user at fetch https://relay.beckmeyer.us/actor, {:content_type, "application/json; charset=utf-8"}
00:12:33.539 [error] error: :not_found
Error while following https://relay.beckmeyer.us/actor: :not_found
Following the built-in relays of Pleroma instances works fine, however.
The problem is that ActivityRelay returns Content-Type: application/json; charset=utf-8
instead of Content-Type: application/activity+json
for the relay actor, thus fetching it fails the validation from 6ca70981.
A possible fix is to just allow application/json
as a content type, i.e.
diff --git a/lib/pleroma/object/fetcher.ex b/lib/pleroma/object/fetcher.ex
index 20d8f687d..92cb1d7d9 100644
--- a/lib/pleroma/object/fetcher.ex
+++ b/lib/pleroma/object/fetcher.ex
@@ -226,6 +226,9 @@ defp get_object(id) do
{:ok, "application", "activity+json", _} ->
{:ok, body}
+ {:ok, "application", "json", _} ->
+ {:ok, body}
+
{:ok, "application", "ld+json",
%{"profile" => "https://www.w3.org/ns/activitystreams"}} ->
{:ok, body}
But in the light of #1948 (closed), this seems ill-advised. Maybe we could relax the filter only if we're fetching /actor
from a remote server? (Relaxing the filter only when we're following a relay is also a possibility, but I wonder if there are any situation when we're fetching a relay actor outside of following it.)
An alternative fix is courtesy of JoelB[m]
from the #pleroma
IRC channel: https://matrix.org/_matrix/media/r0/download/matrix.org/zVXXPCARkapYUeQnoQewugwL/message.txt, i.e. just make sure ActivityRelay sends the correct content type. However, this wouldn't be tenable in the short term, either, because existing ActivityRelay instances would all need to update for the fix to take effect.
After applying my fix (relax the filter), I could follow Since then, I could follow another relay just fine and it followed back, so it's probably enough to update the content type filter.JoelB[m]
's test relay instance. If eventually followed me back, but only after JoelB[m]
patched the relay source code, so I don't know whether following back just has a delay, of actually the second fix was needed for it to work.
I wonder what the ActivityPub specification says in this case? What is the correct content type for actors?