migrate source Protocol in /convert/ endpoints from path to subdomain

for #512, #548
deploy
Ryan Barrett 2023-06-14 15:02:59 -07:00
rodzic 002c6a9740
commit c2f5cbd35e
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 6BE31FDF4776E9D4
2 zmienionych plików z 55 dodań i 34 usunięć

Wyświetl plik

@ -13,18 +13,17 @@ from oauth_dropins.webutil import flask_util, util
from oauth_dropins.webutil.flask_util import error
from activitypub import ActivityPub
from common import CACHE_TIME
from common import CACHE_TIME, SUPERDOMAIN
from flask_app import app, cache
from models import Object, PROTOCOLS
from protocol import Protocol
from web import Web
logger = logging.getLogger(__name__)
SOURCES = frozenset((
ActivityPub.ABBREV,
ActivityPub.LABEL,
Web.ABBREV,
Web.LABEL,
ActivityPub,
Web,
))
DESTS = frozenset((
ActivityPub.ABBREV,
@ -34,17 +33,21 @@ DESTS = frozenset((
))
@app.get(f'/convert/<any({",".join(SOURCES)}):src>/<any({",".join(DESTS)}):dest>/<path:_>')
@app.get(f'/convert/<any({",".join(DESTS)}):dest>/<path:_>')
@flask_util.cached(cache, CACHE_TIME, headers=['Accept'])
def convert(src, dest, _):
def convert(dest, _):
"""Converts data from one protocol to another and serves it.
Fetches the source data if it's not already stored.
"""
src_cls = Protocol.for_request()
if not src_cls:
error(f'Unknown protocol {request.host.removesuffix(SUPERDOMAIN)}', status=404)
# don't use urllib.parse.urlencode(request.args) because that doesn't
# guarantee us the same query param string as in the original URL, and we
# want exactly the same thing since we're looking up the URL's Object by id
path_prefix = f'convert/{src}/{dest}/'
path_prefix = f'convert/{dest}/'
url = request.url.removeprefix(request.root_url).removeprefix(path_prefix)
# our redirects evidently collapse :// down to :/ , maybe to prevent URL
@ -56,7 +59,6 @@ def convert(src, dest, _):
# require g.user for AP since postprocess_as2 currently needs it. ugh
dest_cls = PROTOCOLS[dest]
src_cls = PROTOCOLS[src]
if dest_cls == ActivityPub:
domain = util.domain_from_link(url, minimize=False)
g.user = Web.get_by_id(domain)
@ -91,4 +93,4 @@ def convert(src, dest, _):
def render_redirect():
"""Redirect from old /render?id=... endpoint to /convert/..."""
id = flask_util.get_required_param('id')
return redirect(f'/convert/ap/web/{id}', code=301)
return redirect(ActivityPub.subdomain_url(f'/convert/web/{id}'), code=301)

Wyświetl plik

@ -18,8 +18,8 @@ from common import CONTENT_TYPE_HTML
COMMENT_AS2 = {
**as2.to_as1(COMMENT),
'type': 'Note',
'id': 'http://localhost/r/tag:fake.com:123456',
'url': 'http://localhost/r/https://fake.com/123456',
'id': 'https://fed.brid.gy/r/tag:fake.com:123456',
'url': 'https://fed.brid.gy/r/https://fake.com/123456',
'name': 'A ☕ reply',
'inReplyTo': 'https://fake.com/123',
}
@ -69,19 +69,23 @@ AUTHOR_HTML = """\
class ConvertTest(testutil.TestCase):
def test_unknown_source(self):
resp = self.client.get('/convert/nope/web/http://foo')
resp = self.client.get('/convert/web/http://foo',
base_url='https://nope.brid.gy/')
self.assertEqual(404, resp.status_code)
def test_unknown_dest(self):
resp = self.client.get('/convert/ap/nope/http://foo')
resp = self.client.get('/convert/nope/http://foo',
base_url='https://ap.brid.gy/')
self.assertEqual(404, resp.status_code)
def test_missing_url(self):
resp = self.client.get('/convert/ap/web/')
resp = self.client.get('/convert/web/',
base_url='https://ap.brid.gy/')
self.assertEqual(404, resp.status_code)
def test_url_not_web(self):
resp = self.client.get('/convert/ap/web/git+ssh://foo/bar')
resp = self.client.get('/convert/web/git+ssh://foo/bar',
base_url='https://ap.brid.gy/')
self.assertEqual(400, resp.status_code)
def test_activitypub_to_web_object(self):
@ -89,7 +93,8 @@ class ConvertTest(testutil.TestCase):
with self.request_context:
Object(id=url, our_as1=COMMENT).put()
resp = self.client.get('/convert/ap/web/https://user.com/bar?baz=baj&biff')
resp = self.client.get('/convert/web/https://user.com/bar?baz=baj&biff',
base_url='https://ap.brid.gy/')
self.assertEqual(200, resp.status_code)
self.assert_multiline_equals(HTML, resp.get_data(as_text=True),
ignore_blanks=True)
@ -98,7 +103,8 @@ class ConvertTest(testutil.TestCase):
with self.request_context:
Object(id='http://foo').put()
resp = self.client.get('/convert/ap/web/http://foo')
resp = self.client.get('/convert/web/http://foo',
base_url='https://ap.brid.gy/')
self.assertEqual(404, resp.status_code)
@patch('requests.get')
@ -106,7 +112,8 @@ class ConvertTest(testutil.TestCase):
mock_get.return_value = self.as2_resp(as2.from_as1(COMMENT))
url = 'https://user.com/bar?baz=baj&biff'
resp = self.client.get(f'/convert/ap/web/{url}')
resp = self.client.get(f'/convert/web/{url}',
base_url='https://ap.brid.gy/')
self.assertEqual(200, resp.status_code)
self.assertEqual(CONTENT_TYPE_HTML, resp.content_type)
self.assert_multiline_equals(HTML, resp.get_data(as_text=True),
@ -118,7 +125,8 @@ class ConvertTest(testutil.TestCase):
def test_activitypub_to_web_fetch_fails(self, mock_get):
mock_get.side_effect = [requests_response('', status=405)]
resp = self.client.get('/convert/ap/web/http://foo')
resp = self.client.get('/convert/web/http://foo',
base_url='https://ap.brid.gy/')
self.assertEqual(502, resp.status_code)
mock_get.assert_has_calls((self.as2_req('http://foo'),))
@ -129,7 +137,8 @@ class ConvertTest(testutil.TestCase):
Object(id='http://bar', our_as1=ACTOR,
source_protocol='activitypub').put()
resp = self.client.get('/convert/ap/web/http://foo')
resp = self.client.get('/convert/web/http://foo',
base_url='https://ap.brid.gy/')
self.assertEqual(200, resp.status_code)
self.assert_multiline_equals(AUTHOR_HTML, resp.get_data(as_text=True),
ignore_blanks=True)
@ -140,7 +149,8 @@ class ConvertTest(testutil.TestCase):
with self.request_context:
Object(id='http://foo', our_as1=comment).put()
resp = self.client.get('/convert/ap/web/http://foo')
resp = self.client.get('/convert/web/http://foo',
base_url='https://ap.brid.gy/')
self.assertEqual(200, resp.status_code)
expected = HTML.replace(
'\n<meta http-equiv="refresh" content="0;url=https://fake.com/123456">', ''
@ -152,14 +162,16 @@ class ConvertTest(testutil.TestCase):
with self.request_context:
Object(id='http://foo', as2={'content': 'foo'}, deleted=True).put()
resp = self.client.get('/convert/ap/web/http://foo')
resp = self.client.get('/convert/web/http://foo',
base_url='https://ap.brid.gy/')
self.assertEqual(410, resp.status_code)
def test_activitypub_to_web_delete_activity(self):
with self.request_context:
Object(id='http://foo', our_as1=DELETE_OF_ID).put()
resp = self.client.get('/convert/ap/web/http://foo')
resp = self.client.get('/convert/web/http://foo',
base_url='https://ap.brid.gy/')
self.assertEqual(410, resp.status_code)
def test_activitypub_to_web_update_inner_obj_exists_redirect(self):
@ -168,9 +180,10 @@ class ConvertTest(testutil.TestCase):
Object(id='http://foo', our_as1=UPDATE).put()
Object(id=UPDATE['object']['id'], as2={'content': 'foo'}).put()
resp = self.client.get('/convert/ap/web/http://foo')
resp = self.client.get('/convert/web/http://foo',
base_url='https://ap.brid.gy/')
self.assertEqual(301, resp.status_code)
self.assertEqual(f'/convert/ap/web/tag:fake.com:123456',
self.assertEqual(f'/convert/web/tag:fake.com:123456',
resp.headers['Location'])
def test_activitypub_to_web_delete_inner_obj_exists_redirect(self):
@ -179,9 +192,10 @@ class ConvertTest(testutil.TestCase):
Object(id='http://foo', our_as1=DELETE_OF_ID).put()
Object(id=DELETE_OF_ID['object'], as2={'content': 'foo'}).put()
resp = self.client.get('/convert/ap/web/http://foo')
resp = self.client.get('/convert/web/http://foo',
base_url='https://ap.brid.gy/')
self.assertEqual(301, resp.status_code)
self.assertEqual(f'/convert/ap/web/tag:fake.com:123456',
self.assertEqual(f'/convert/web/tag:fake.com:123456',
resp.headers['Location'])
def test_activitypub_to_web_update_no_inner_obj_serve_as_is(self):
@ -189,7 +203,8 @@ class ConvertTest(testutil.TestCase):
# UPDATE's object field is a full object
Object(id='http://foo', our_as1=UPDATE).put()
resp = self.client.get('/convert/ap/web/http://foo')
resp = self.client.get('/convert/web/http://foo',
base_url='https://ap.brid.gy/')
self.assertEqual(200, resp.status_code)
self.assert_multiline_in("""\
<div class="e-content p-name">
@ -204,7 +219,8 @@ A ☕ reply
Object(id='http://foo', our_as1=UPDATE).put()
Object(id=UPDATE['object']['id'], as2={'id': 'foo'}).put()
resp = self.client.get('/convert/ap/web/http://foo')
resp = self.client.get('/convert/web/http://foo',
base_url='https://ap.brid.gy/')
self.assertEqual(200, resp.status_code)
self.assert_multiline_in("""\
<div class="e-content p-name">
@ -216,7 +232,7 @@ A ☕ reply
def test_render_endpoint_redirect(self):
resp = self.client.get('/render?id=http://foo%3Fbar')
self.assertEqual(301, resp.status_code)
self.assertEqual(f'/convert/ap/web/http://foo?bar',
self.assertEqual(f'https://ap.brid.gy/convert/web/http://foo?bar',
resp.headers['Location'])
def test_web_to_activitypub_object(self):
@ -226,7 +242,8 @@ A ☕ reply
with self.request_context:
Object(id=url, mf2=parse_mf2(HTML)['items'][0]).put()
resp = self.client.get(f'/convert/web/ap/{url}')
resp = self.client.get(f'/convert/ap/{url}',
base_url='https://ap.brid.gy/')
self.assertEqual(200, resp.status_code)
self.assert_equals(COMMENT_AS2, resp.json, ignore=['to'])
@ -239,11 +256,13 @@ A ☕ reply
with self.request_context:
Object(id=url, mf2=parse_mf2(HTML)['items'][0]).put()
resp = self.client.get(f'/convert/web/ap/{url}')
resp = self.client.get(f'/convert/ap/{url}',
base_url='https://web.brid.gy/')
self.assertEqual(200, resp.status_code)
self.assert_equals(COMMENT_AS2, resp.json, ignore=['to'])
def test_web_to_activitypub_no_user(self):
resp = self.client.get(f'/convert/web/ap/http://nope.com/post')
resp = self.client.get(f'/convert/ap/http://nope.com/post',
base_url='https://ap.brid.gy/')
self.assertEqual(400, resp.status_code)