kopia lustrzana https://github.com/snarfed/bridgy-fed
rodzic
002c6a9740
commit
c2f5cbd35e
22
convert.py
22
convert.py
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue