1# Copyright (C) 2018 The Android Open Source Project 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15from google.appengine.api import memcache 16from google.appengine.api import urlfetch 17 18import re 19import webapp2 20 21MEMCACHE_TTL_SEC= 60 * 60 * 24 22BASE = 'https://catapult-project.github.io/perfetto/%s' 23HEADERS = {'last-modified', 'content-type', 24 'content-length', 'content-encoding', 'etag'} 25 26 27class MainHandler(webapp2.RequestHandler): 28 def get(self): 29 handler = GithubMirrorHandler() 30 handler.initialize(self.request, self.response) 31 return handler.get("index.html") 32 33 34class GithubMirrorHandler(webapp2.RequestHandler): 35 def get(self, resource): 36 if not re.match('^[a-zA-Z0-9-_./]*$', resource): 37 self.response.set_status(403) 38 return 39 40 url = BASE % resource 41 cache = memcache.get(url) 42 if not cache or self.request.get('reload'): 43 result = urlfetch.fetch(url) 44 if result.status_code != 200: 45 memcache.delete(url) 46 self.response.set_status(result.status_code) 47 self.response.write(result.content) 48 return 49 cache = {'content-type': 'text/html'} 50 for k, v in result.headers.iteritems(): 51 k = k.lower() 52 if k in HEADERS: 53 cache[k] = v 54 cache['content'] = result.content 55 memcache.set(url, cache, time=MEMCACHE_TTL_SEC) 56 57 for k, v in cache.iteritems(): 58 if k != 'content': 59 self.response.headers[k] = v 60 self.response.headers['cache-control'] = 'public,max-age=600' 61 self.response.write(cache['content']) 62 63 64app = webapp2.WSGIApplication([ 65 ('/', MainHandler), 66 ('/(.+)', GithubMirrorHandler), 67], debug=True) 68