kopia lustrzana https://github.com/snarfed/bridgy-fed
				
				
				
			add new /render endpoint for rendering Responses as HTML
							rodzic
							
								
									6a65e2e74a
								
							
						
					
					
						commit
						98465907ff
					
				
							
								
								
									
										4
									
								
								app.yaml
								
								
								
								
							
							
						
						
									
										4
									
								
								app.yaml
								
								
								
								
							| 
						 | 
				
			
			@ -74,6 +74,10 @@ handlers:
 | 
			
		|||
  script: salmon.app
 | 
			
		||||
  secure: always
 | 
			
		||||
 | 
			
		||||
- url: /render
 | 
			
		||||
  script: render.app
 | 
			
		||||
  secure: always
 | 
			
		||||
 | 
			
		||||
- url: /(acct:)?[^/]+/?
 | 
			
		||||
  script: webfinger.app
 | 
			
		||||
  secure: always
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,42 @@
 | 
			
		|||
# coding=utf-8
 | 
			
		||||
"""Renders mf2 proxy pages based on stored Responses."""
 | 
			
		||||
import json
 | 
			
		||||
 | 
			
		||||
import appengine_config
 | 
			
		||||
 | 
			
		||||
from granary import as2, microformats2
 | 
			
		||||
from oauth_dropins.webutil.handlers import ModernHandler
 | 
			
		||||
from oauth_dropins.webutil import util
 | 
			
		||||
import webapp2
 | 
			
		||||
 | 
			
		||||
from models import Response
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class RenderHandler(ModernHandler):
 | 
			
		||||
    """Fetches a stored Response and renders it as HTML."""
 | 
			
		||||
 | 
			
		||||
    def get(self):
 | 
			
		||||
        source = util.get_required_param(self, 'source')
 | 
			
		||||
        target = util.get_required_param(self, 'target')
 | 
			
		||||
 | 
			
		||||
        id = '%s %s' % (source, target)
 | 
			
		||||
        resp = Response.get_by_id(id)
 | 
			
		||||
        if not resp:
 | 
			
		||||
            self.abort(404, 'No stored response for %s' % id)
 | 
			
		||||
 | 
			
		||||
        if resp.source_mf2:
 | 
			
		||||
            as1 = microformats2.json_to_object(json.loads(resp.source_mf2))
 | 
			
		||||
        elif resp.source_as2:
 | 
			
		||||
            as1 = as2.to_as1(json.loads(resp.source_as2))
 | 
			
		||||
        elif resp.source_atom:
 | 
			
		||||
            self.abort(501, 'Rendering HTML from Atom is not yet implemented.')
 | 
			
		||||
        else:
 | 
			
		||||
            self.abort(404, 'Stored response for %s has no data' % id)
 | 
			
		||||
 | 
			
		||||
        self.response.write(microformats2.activities_to_html([as1]))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
app = webapp2.WSGIApplication([
 | 
			
		||||
    ('/render', RenderHandler),
 | 
			
		||||
], debug=appengine_config.DEBUG)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,74 @@
 | 
			
		|||
# coding=utf-8
 | 
			
		||||
"""Unit tests for render.py."""
 | 
			
		||||
from __future__ import unicode_literals
 | 
			
		||||
import json
 | 
			
		||||
 | 
			
		||||
from models import Response
 | 
			
		||||
import testutil
 | 
			
		||||
from render import app
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class RenderTest(testutil.TestCase):
 | 
			
		||||
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        super(RenderTest, self).setUp()
 | 
			
		||||
 | 
			
		||||
        self.as2 = {
 | 
			
		||||
            '@context': 'https://www.w3.org/ns/activitystreams',
 | 
			
		||||
            'type': 'Note',
 | 
			
		||||
            'content': 'A ☕ reply',
 | 
			
		||||
            'url': 'http://this/reply',
 | 
			
		||||
            'inReplyTo': 'http://orig/post',
 | 
			
		||||
        }
 | 
			
		||||
        self.mf2 = {
 | 
			
		||||
            'type': ['h-entry'],
 | 
			
		||||
            'properties': {
 | 
			
		||||
                'url': ['http://this/reply'],
 | 
			
		||||
                'content': [{'value': 'A ☕ reply'}],
 | 
			
		||||
                'in-reply-to': ['http://orig/post'],
 | 
			
		||||
            },
 | 
			
		||||
        }
 | 
			
		||||
        self.html = """\
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html>
 | 
			
		||||
<head><meta charset="utf-8"></head>
 | 
			
		||||
<body>
 | 
			
		||||
<article class="h-entry">
 | 
			
		||||
  <span class="p-uid"></span>
 | 
			
		||||
  <a class="u-url" href="http://this/reply">http://this/reply</a>
 | 
			
		||||
  <div class="e-content p-name">
 | 
			
		||||
  A ☕ reply
 | 
			
		||||
  </div>
 | 
			
		||||
  <a class="u-in-reply-to" href="http://orig/post"></a>
 | 
			
		||||
</article>
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
    def test_render_errors(self):
 | 
			
		||||
        for source, target in ('', ''), ('abc', ''), ('', 'xyz'):
 | 
			
		||||
            resp = app.get_response('/render?source=%s&target=%s' % (source, target))
 | 
			
		||||
            self.assertEquals(400, resp.status_int, resp.body)
 | 
			
		||||
 | 
			
		||||
        # no Response
 | 
			
		||||
        resp = app.get_response('/render?source=abc&target=xyz')
 | 
			
		||||
        self.assertEquals(404, resp.status_int)
 | 
			
		||||
 | 
			
		||||
        # no source data
 | 
			
		||||
        Response(id='abc xyz').put()
 | 
			
		||||
        resp = app.get_response('/render?source=abc&target=xyz')
 | 
			
		||||
        self.assertEquals(404, resp.status_int)
 | 
			
		||||
 | 
			
		||||
    def test_render_as2(self):
 | 
			
		||||
        Response(id='abc xyz', source_as2=json.dumps(self.as2)).put()
 | 
			
		||||
        resp = app.get_response('/render?source=abc&target=xyz')
 | 
			
		||||
        self.assertEquals(200, resp.status_int)
 | 
			
		||||
        self.assert_multiline_equals(self.html, resp.body.decode('utf-8'),
 | 
			
		||||
                                     ignore_blanks=True)
 | 
			
		||||
 | 
			
		||||
    def test_render_mf2(self):
 | 
			
		||||
        Response(id='abc xyz', source_mf2=json.dumps(self.mf2)).put()
 | 
			
		||||
        resp = app.get_response('/render?source=abc&target=xyz')
 | 
			
		||||
        self.assertEquals(200, resp.status_int)
 | 
			
		||||
        self.assert_multiline_equals(self.html, resp.body.decode('utf-8'),
 | 
			
		||||
                                     ignore_blanks=True)
 | 
			
		||||
| 
						 | 
				
			
			@ -5,8 +5,10 @@ import unittest
 | 
			
		|||
from google.appengine.datastore import datastore_stub_util
 | 
			
		||||
from google.appengine.ext import testbed
 | 
			
		||||
 | 
			
		||||
from oauth_dropins.webutil import testutil
 | 
			
		||||
 | 
			
		||||
class TestCase(unittest.TestCase):
 | 
			
		||||
 | 
			
		||||
class TestCase(unittest.TestCase, testutil.Asserts):
 | 
			
		||||
 | 
			
		||||
    maxDiff = None
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Ładowanie…
	
		Reference in New Issue