Chromium Code Reviews| Index: appengine/isolate/handlers_frontend.py |
| diff --git a/appengine/isolate/handlers_frontend.py b/appengine/isolate/handlers_frontend.py |
| index 63c8853c14d2e7866c0b1c84a7b0d98cf2fd2128..ac2a5d1e98eff4f9bd4c4d9bff6a6cd024039a7d 100644 |
| --- a/appengine/isolate/handlers_frontend.py |
| +++ b/appengine/isolate/handlers_frontend.py |
| @@ -6,6 +6,7 @@ |
| import datetime |
| import json |
| +import re |
| import webapp2 |
| @@ -151,6 +152,34 @@ class BrowseHandler(auth.AuthenticatingHandler): |
| namespace = self.request.get('namespace', 'default-gzip') |
| # Support 'hash' for compatibility with old links. To remove eventually. |
| digest = self.request.get('digest', '') or self.request.get('hash', '') |
| + params = { |
| + u'digest': unicode(digest), |
| + u'namespace': unicode(namespace), |
| + # TODO(maruel): Add back once Web UI authentication is switched to OAuth2. |
|
M-A Ruel
2016/04/13 20:32:09
Remove this while at it, not needed.
kjlubick
2016/04/14 13:18:43
Done.
kjlubick
2016/04/14 13:18:43
Done.
|
| + #'onload': 'update()' if digest else '', |
| + u'onload': '', |
| + } |
| + # Check for existence of element, so we can 400/404 |
| + if digest and namespace: |
| + # TODO(maruel): Refactor into a function. |
|
M-A Ruel
2016/04/13 20:32:09
Can you make it a function now that it is used at
kjlubick
2016/04/14 13:18:43
I put it in model.py and used it twice here. I co
|
| + memcache_entry = memcache.get(digest, namespace='table_%s' % namespace) |
| + if memcache_entry is None: |
| + try: |
| + key = model.get_entry_key(namespace, digest) |
| + except ValueError: |
| + self.abort(400, 'Invalid key') |
| + entity = key.get() |
| + if entity is None: |
| + self.abort(404, 'Unable to retrieve the entry') |
| + self.response.write(template.render('isolate/browse.html', params)) |
| + |
|
M-A Ruel
2016/04/13 20:32:09
2 empty lines between file level symbols
kjlubick
2016/04/14 13:18:43
Done.
|
| +class ContentHandler(auth.AuthenticatingHandler): |
| + @auth.autologin |
| + @auth.require(acl.isolate_readable) |
| + def get(self): |
| + namespace = self.request.get('namespace', 'default-gzip') |
| + digest = self.request.get('digest', '') |
| + |
| content = None |
| if digest and namespace: |
| # TODO(maruel): Refactor into a function. |
| @@ -171,24 +200,34 @@ class BrowseHandler(auth.AuthenticatingHandler): |
| else: |
| stream = [raw_data] |
| content = ''.join(model.expand_content(namespace, stream)) |
| + |
| + self.response.headers['X-Frame-Options'] = 'SAMEORIGIN' |
| + del self.response.headers['Content-Type'] |
| + # Apparently, setting the content type to text/plain encourages the |
| + # browser (Chrome, at least) to sniff the mime type and display |
| + # things like images. Images are autowrapped in <img> and text is |
| + # wrapped in <pre>. |
| + self.response.headers['Content-Type'] = 'text/plain; charset=utf-8' |
| + self.response.headers['Content-Disposition'] = str('filename=%s' % digest) |
| if content.startswith('{'): |
| # Try to format as JSON. |
| try: |
| content = json.dumps( |
| json.loads(content), sort_keys=True, indent=2, |
| separators=(',', ': ')) |
| + content = ( |
| + '<div style="font-family:monospace;white-space:pre-wrap;">%s</div>' |
|
M-A Ruel
2016/04/13 20:32:09
Looks like this is not strictly necessary from wha
kjlubick
2016/04/14 13:18:43
I'll add a comment that mirrors this, but I don't
|
| + % content) |
| + # Linkify things that look like hashes |
| + content = re.sub(r'([0-9a-f]{40})', |
| + r"""<a target="_blank" href="browse?namespace=default-gzip |
| + &digest=\1">\1</a>""", |
| + content) |
| + self.response.headers['Content-Type'] = 'text/html; charset=utf-8' |
| except ValueError: |
| pass |
| - content = content.decode('utf8', 'replace') |
| - params = { |
| - u'content': content, |
| - u'digest': unicode(digest), |
| - u'namespace': unicode(namespace), |
| - # TODO(maruel): Add back once Web UI authentication is switched to OAuth2. |
| - #'onload': 'update()' if digest else '', |
| - u'onload': '', |
| - } |
| - self.response.write(template.render('isolate/browse.html', params)) |
| + |
| + self.response.write(content) |
| class StatsHandler(webapp2.RequestHandler): |
| @@ -298,6 +337,7 @@ def get_routes(): |
| # User web pages. |
| webapp2.Route(r'/browse', BrowseHandler), |
| + webapp2.Route(r'/content', ContentHandler), |
| webapp2.Route(r'/stats', StatsHandler), |
| webapp2.Route(r'/isolate/api/v1/stats/days', StatsGvizDaysHandler), |
| webapp2.Route(r'/isolate/api/v1/stats/hours', StatsGvizHoursHandler), |