Handle 410 gone for remote activities

pull/2/head
Thomas Sileo 2018-06-22 23:38:25 +02:00
rodzic dc0081ec10
commit ebcfc6e0a5
3 zmienionych plików z 37 dodań i 7 usunięć

Wyświetl plik

@ -15,9 +15,11 @@ from .backend import Backend
from .collection import parse_collection
from .errors import BadActivityError
from .errors import Error
from .errors import RemoteActivityGoneError
from .errors import NotFromOutboxError
from .errors import UnexpectedActivityTypeError
logger = logging.getLogger(__name__)
UninitializedBackendError = Error("a backend must be initialized")
@ -492,7 +494,12 @@ class BaseActivity(object, metaclass=_ActivityMeta):
continue
actor = recipient
else:
raw_actor = BACKEND.fetch_iri(recipient)
try:
raw_actor = BACKEND.fetch_iri(recipient)
except RemoteActivityGoneError:
logger.info(f"{recipient} is gone")
continue
if raw_actor["type"] == ActivityType.PERSON.value:
actor = Person(**raw_actor)
@ -511,12 +518,19 @@ class BaseActivity(object, metaclass=_ActivityMeta):
ActivityType.ORDERED_COLLECTION.value,
]:
for item in parse_collection(raw_actor, fetcher=BACKEND.fetch_iri):
# XXX(tsileo): is nested collection support needed here?
if item in [actor_id, AS_PUBLIC]:
continue
try:
col_actor = Person(**BACKEND.fetch_iri(item))
col_actor = fetch_remote_activity(
item, expected=ActivityType.PERSON
)
except UnexpectedActivityTypeError:
logger.exception(f"failed to fetch actor {item!r}")
continue
except RemoteActivityGoneError:
logger.info(f"{item} is gone")
continue
if col_actor.endpoints:
shared_inbox = col_actor.endpoints.get("sharedInbox")
@ -1056,7 +1070,9 @@ class Note(BaseActivity):
)
def fetch_remote_activity(iri: str, expected: Optional[ActivityType]) -> BaseActivity:
def fetch_remote_activity(
iri: str, expected: Optional[ActivityType] = None
) -> BaseActivity:
return parse_activity(get_backend().fetch_iri(iri), expected=expected)

Wyświetl plik

@ -7,6 +7,7 @@ import requests
from .__version__ import __version__
from .errors import ActivityNotFoundError
from .errors import RemoteActivityGoneError
from .urlutils import check_url
if typing.TYPE_CHECKING:
@ -31,6 +32,9 @@ class Backend(abc.ABC):
headers={"User-Agent": self.user_agent(), "Accept": "application/json"},
**kwargs,
)
resp.raise_for_status()
return resp
def is_from_outbox(
@ -60,6 +64,8 @@ class Backend(abc.ABC):
)
if resp.status_code == 404:
raise ActivityNotFoundError(f"{iri} is not found")
elif resp.status_code == 410:
raise RemoteActivityGoneError(f"{iri} is gone")
resp.raise_for_status()

Wyświetl plik

@ -5,6 +5,14 @@ from typing import Optional
class Error(Exception):
"""Base error for exceptions raised by this package."""
class RemoteActivityGoneError(Error):
"""Raised when trying to fetch a remote activity that was deleted."""
class ServerError(Error):
"""HTTP-friendly base error, with a status code, a message and an optional payload."""
status_code = 400
@ -36,21 +44,21 @@ class Error(Exception):
return self.__repr__()
class ActorBlockedError(Error):
class ActorBlockedError(ServerError):
"""Raised when an activity from a blocked actor is received."""
class NotFromOutboxError(Error):
class NotFromOutboxError(ServerError):
"""Raised when an activity targets an object from the inbox when an object from the oubox was expected."""
class ActivityNotFoundError(Error):
class ActivityNotFoundError(ServerError):
"""Raised when an activity is not found."""
status_code = 404
class BadActivityError(Error):
class BadActivityError(ServerError):
"""Raised when an activity could not be parsed/initialized."""