return parsed JSON from common.get_as2(); use it in activitypub

pull/27/head
Ryan Barrett 2017-10-20 07:13:04 -07:00
rodzic 527ca5585b
commit e985516dc3
5 zmienionych plików z 25 dodań i 20 usunięć

Wyświetl plik

@ -14,13 +14,6 @@ import webapp2
import common import common
from models import MagicKey from models import MagicKey
# https://www.w3.org/TR/activitypub/#retrieving-objects
CONTENT_TYPE_AS2 = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'
CONTENT_TYPE_AS = 'application/activity+json'
CONNEG_HEADER = {
'Accept': '%s; q=0.9, %s; q=0.8' % (CONTENT_TYPE_AS2, CONTENT_TYPE_AS),
}
SUPPORTED_TYPES = ( SUPPORTED_TYPES = (
'Announce', 'Announce',
'Article', 'Article',
@ -31,6 +24,7 @@ SUPPORTED_TYPES = (
'Video', 'Video',
) )
class ActorHandler(webapp2.RequestHandler): class ActorHandler(webapp2.RequestHandler):
"""Serves /[DOMAIN], fetches its mf2, converts to AS Actor, and serves it.""" """Serves /[DOMAIN], fetches its mf2, converts to AS Actor, and serves it."""
@ -56,7 +50,7 @@ representative h-card</a> on %s""" % resp.url)
logging.info('Returning: %s', json.dumps(obj, indent=2)) logging.info('Returning: %s', json.dumps(obj, indent=2))
self.response.headers.update({ self.response.headers.update({
'Content-Type': CONTENT_TYPE_AS2, 'Content-Type': common.CONTENT_TYPE_AS2,
'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Origin': '*',
}) })
self.response.write(json.dumps(obj, indent=2)) self.response.write(json.dumps(obj, indent=2))
@ -86,8 +80,7 @@ class InboxHandler(webapp2.RequestHandler):
if activity.get('type') in ('Like', 'Announce'): if activity.get('type') in ('Like', 'Announce'):
actor = activity.get('actor') actor = activity.get('actor')
if actor: if actor:
activity['actor'] = common.requests_get( activity['actor'] = common.get_as2(actor)
actor, parse_json=True, headers=CONNEG_HEADER)
# send webmentions to each target # send webmentions to each target
as1 = as2.to_as1(activity) as1 = as2.to_as1(activity)

Wyświetl plik

@ -95,7 +95,7 @@ def get_as2(url):
url: string url: string
Returns: Returns:
requests.Response dict, AS2 object parsed from JSON
Raises: Raises:
requests.HTTPError, webob.exc.HTTPException requests.HTTPError, webob.exc.HTTPException
@ -107,7 +107,7 @@ def get_as2(url):
resp = requests_get(url, headers=CONNEG_HEADERS_AS2_HTML) resp = requests_get(url, headers=CONNEG_HEADERS_AS2_HTML)
if resp.headers.get('Content-Type') in (CONTENT_TYPE_AS2, CONTENT_TYPE_AS2_LD): if resp.headers.get('Content-Type') in (CONTENT_TYPE_AS2, CONTENT_TYPE_AS2_LD):
return resp return resp.json()
parsed = BeautifulSoup(resp.content, from_encoding=resp.encoding) parsed = BeautifulSoup(resp.content, from_encoding=resp.encoding)
as2 = parsed.find('link', rel=('alternate', 'self'), type=( as2 = parsed.find('link', rel=('alternate', 'self'), type=(
@ -118,7 +118,7 @@ def get_as2(url):
resp = requests_get(urlparse.urljoin(resp.url, as2['href']), resp = requests_get(urlparse.urljoin(resp.url, as2['href']),
headers=CONNEG_HEADERS_AS2) headers=CONNEG_HEADERS_AS2)
if resp.headers.get('Content-Type') in (CONTENT_TYPE_AS2, CONTENT_TYPE_AS2_LD): if resp.headers.get('Content-Type') in (CONTENT_TYPE_AS2, CONTENT_TYPE_AS2_LD):
return resp return resp.json()
_error() _error()

Wyświetl plik

@ -35,7 +35,7 @@ class ActivityPubTest(testutil.TestCase):
mock_get.assert_called_once_with('http://foo.com/', headers=common.HEADERS, mock_get.assert_called_once_with('http://foo.com/', headers=common.HEADERS,
timeout=util.HTTP_TIMEOUT) timeout=util.HTTP_TIMEOUT)
self.assertEquals(200, got.status_int) self.assertEquals(200, got.status_int)
self.assertEquals(activitypub.CONTENT_TYPE_AS2, got.headers['Content-Type']) self.assertEquals(common.CONTENT_TYPE_AS2, got.headers['Content-Type'])
self.assertEquals({ self.assertEquals({
'@context': 'https://www.w3.org/ns/activitystreams', '@context': 'https://www.w3.org/ns/activitystreams',
'type' : 'Person', 'type' : 'Person',
@ -111,7 +111,7 @@ class ActivityPubTest(testutil.TestCase):
} }
mock_get.side_effect = [ mock_get.side_effect = [
# source actor # source actor
requests_response(actor), requests_response(actor, headers={'Content-Type': common.CONTENT_TYPE_AS2}),
# target post webmention discovery # target post webmention discovery
requests_response( requests_response(
'<html><head><link rel="webmention" href="/webmention"></html>'), '<html><head><link rel="webmention" href="/webmention"></html>'),
@ -134,7 +134,7 @@ class ActivityPubTest(testutil.TestCase):
self.assertEquals(200, got.status_int) self.assertEquals(200, got.status_int)
as2_headers = copy.deepcopy(common.HEADERS) as2_headers = copy.deepcopy(common.HEADERS)
as2_headers.update(activitypub.CONNEG_HEADER) as2_headers.update(common.CONNEG_HEADERS_AS2_HTML)
mock_get.assert_has_calls(( mock_get.assert_has_calls((
call('http://orig/actor', headers=as2_headers, timeout=15), call('http://orig/actor', headers=as2_headers, timeout=15),
call('http://orig/post', headers=common.HEADERS, verify=False), call('http://orig/post', headers=common.HEADERS, verify=False),

Wyświetl plik

@ -23,7 +23,8 @@ HTML_WITH_AS2 = requests_response("""\
""", headers={ """, headers={
'Content-Type': common.CONTENT_TYPE_HTML, 'Content-Type': common.CONTENT_TYPE_HTML,
}) })
AS2 = requests_response({}, headers={ AS2_OBJ = {'foo': ['bar']}
AS2 = requests_response(AS2_OBJ, headers={
'Content-Type': common.CONTENT_TYPE_AS2, 'Content-Type': common.CONTENT_TYPE_AS2,
}) })
NOT_ACCEPTABLE = requests_response(status=406) NOT_ACCEPTABLE = requests_response(status=406)
@ -34,7 +35,7 @@ class CommonTest(testutil.TestCase):
@mock.patch('requests.get', return_value=AS2) @mock.patch('requests.get', return_value=AS2)
def test_get_as2_direct(self, mock_get): def test_get_as2_direct(self, mock_get):
resp = common.get_as2('http://orig') resp = common.get_as2('http://orig')
self.assertEqual(AS2, resp) self.assertEqual(AS2_OBJ, resp)
mock_get.assert_has_calls(( mock_get.assert_has_calls((
self.req('http://orig', headers=common.CONNEG_HEADERS_AS2_HTML), self.req('http://orig', headers=common.CONNEG_HEADERS_AS2_HTML),
)) ))
@ -42,7 +43,7 @@ class CommonTest(testutil.TestCase):
@mock.patch('requests.get', side_effect=[HTML_WITH_AS2, AS2]) @mock.patch('requests.get', side_effect=[HTML_WITH_AS2, AS2])
def test_get_as2_via_html(self, mock_get): def test_get_as2_via_html(self, mock_get):
resp = common.get_as2('http://orig') resp = common.get_as2('http://orig')
self.assertEqual(AS2, resp) self.assertEqual(AS2_OBJ, resp)
mock_get.assert_has_calls(( mock_get.assert_has_calls((
self.req('http://orig', headers=common.CONNEG_HEADERS_AS2_HTML), self.req('http://orig', headers=common.CONNEG_HEADERS_AS2_HTML),
self.req('http://as2', headers=common.CONNEG_HEADERS_AS2), self.req('http://as2', headers=common.CONNEG_HEADERS_AS2),

Wyświetl plik

@ -1,11 +1,14 @@
"""Common test utility code. """Common test utility code.
""" """
import copy
import unittest import unittest
from google.appengine.datastore import datastore_stub_util from google.appengine.datastore import datastore_stub_util
from google.appengine.ext import testbed from google.appengine.ext import testbed
from mock import call
from oauth_dropins.webutil import testutil, util
from oauth_dropins.webutil import testutil import common
class TestCase(unittest.TestCase, testutil.Asserts): class TestCase(unittest.TestCase, testutil.Asserts):
@ -24,3 +27,11 @@ class TestCase(unittest.TestCase, testutil.Asserts):
def tearDown(self): def tearDown(self):
self.testbed.deactivate() self.testbed.deactivate()
super(TestCase, self).tearDown() super(TestCase, self).tearDown()
def req(self, url, **kwargs):
"""Returns a mock requests call."""
headers = copy.deepcopy(common.HEADERS)
headers.update(kwargs.get('headers', {}))
kwargs['headers'] = headers
kwargs.setdefault('timeout', util.HTTP_TIMEOUT)
return call(url, **kwargs)