From 33c5c3a4d2382e908f499af2a3922b93a30a12bb Mon Sep 17 00:00:00 2001 From: Ryan Barrett Date: Thu, 23 Nov 2023 22:41:52 -0800 Subject: [PATCH] AP: add HEAD support to followers/ing, outbox collections for #383 --- activitypub.py | 11 +++++++++-- tests/test_activitypub.py | 10 ++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/activitypub.py b/activitypub.py index 59fd6b3..b7c727a 100644 --- a/activitypub.py +++ b/activitypub.py @@ -875,7 +875,8 @@ def inbox(protocol=None, id=None): # source protocol in path; primarily for backcompat @app.get(f'/ap/web//') # special case Web users without /ap/web/ prefix, for backward compatibility -@app.get(f'//') +@app.route(f'//', + methods=['GET', 'HEAD']) @flask_util.cached(cache, CACHE_TIME) def follower_collection(id, collection): """ActivityPub Followers and Following collections. @@ -892,6 +893,9 @@ def follower_collection(id, collection): if not user: return f'{protocol} user {id} not found', 404 + if request.method == 'HEAD': + return '', {'Content-Type': as2.CONTENT_TYPE} + # page followers, new_before, new_after = Follower.fetch_page(collection, user=user) page = { @@ -931,7 +935,7 @@ def follower_collection(id, collection): # source protocol in path; primarily for backcompat @app.get(f'/ap/web//outbox') # special case Web users without /ap/web/ prefix, for backward compatibility -@app.get(f'//outbox') +@app.route(f'//outbox', methods=['GET', 'HEAD']) @flask_util.cached(cache, CACHE_TIME) def outbox(id): """Serves a user's AP outbox. @@ -946,6 +950,9 @@ def outbox(id): if not g.user: error(f'User {id} not found', status=404) + if request.method == 'HEAD': + return '', {'Content-Type': as2.CONTENT_TYPE} + query = Object.query(Object.users == g.user.key) objects, new_before, new_after = fetch_objects(query, by=Object.updated, user=g.user) diff --git a/tests/test_activitypub.py b/tests/test_activitypub.py index 79cac91..374348e 100644 --- a/tests/test_activitypub.py +++ b/tests/test_activitypub.py @@ -1558,6 +1558,11 @@ class ActivityPubTest(TestCase): 'items': [ACTOR], }, resp.json) + def test_following_collection_head(self, *_): + resp = self.client.head(f'/user.com/following') + self.assertEqual(200, resp.status_code) + self.assertEqual('', resp.get_data(as_text=True)) + def test_outbox_fake_empty(self, *_): self.make_user('fake:foo', cls=Fake) resp = self.client.get(f'/ap/fake:foo/outbox', @@ -1641,6 +1646,11 @@ class ActivityPubTest(TestCase): }, }, resp.json) + def test_outbox_web_head(self, *_): + resp = self.client.head(f'/user.com/outbox') + self.assertEqual(200, resp.status_code) + self.assertEqual('', resp.get_data(as_text=True)) + class ActivityPubUtilsTest(TestCase): def setUp(self):