Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(500)

Unified Diff: utils/apidoc/app_engine/scripts/redirector.py

Issue 10831002: serve api docs from cloud storage (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: tweaks from review Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « utils/apidoc/app_engine/app.yaml ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: utils/apidoc/app_engine/scripts/redirector.py
diff --git a/utils/apidoc/app_engine/scripts/redirector.py b/utils/apidoc/app_engine/scripts/redirector.py
index d1260901b0d53f6a58468cdd3cacf6262df6650b..235d0b5c984267f00e819048da1bebcce71ba6a9 100644
--- a/utils/apidoc/app_engine/scripts/redirector.py
+++ b/utils/apidoc/app_engine/scripts/redirector.py
@@ -2,18 +2,121 @@
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
-import webapp2
+import logging
+import re
+from webapp2 import *
+from datetime import datetime, timedelta
+from google.appengine.ext import blobstore
+from google.appengine.ext.webapp import blobstore_handlers
+from google.appengine.api import files, memcache
+
+LATEST_DOC_VERSION_FILE = '/gs/dartlang-api-docs/latest.txt'
+ONE_HOUR = 60 * 60
+ONE_DAY = ONE_HOUR * 24
+ONE_WEEK = ONE_DAY * 7
+
+class ApiDocs(blobstore_handlers.BlobstoreDownloadHandler):
+
+ latest_doc_version = None
+ next_doc_version_check = None
+
+ def reload_latest_version(self):
+ logging.info("Reloading the latest doc version pointer")
+ with files.open(LATEST_DOC_VERSION_FILE, 'r') as f:
+ data = f.read(100)
+ ApiDocs.latest_doc_version = int(data.strip())
+ ApiDocs.next_doc_version_check = datetime.now() + timedelta(days=1)
+
+ # TODO: put into memcache?
+ def get_latest_version(self):
+ forced_reload = self.request.get('force_reload')
+ if (forced_reload or
+ ApiDocs.latest_doc_version is None or
+ ApiDocs.next_doc_version_check is None or
+ datetime.now() > ApiDocs.next_doc_version_check):
+ self.reload_latest_version()
+ return ApiDocs.latest_doc_version
+
+ def get_cache_age(self, path):
+ if re.search(r'(png|jpg)$', path):
+ age = ONE_DAY
+ elif path.endswith('.ico'):
+ age = ONE_WEEK
+ else:
+ age = ONE_HOUR
+ return age
+
+ def resolve_doc_path(self):
+ if self.request.path.startswith('/docs/latest'):
+ version = self.get_latest_version()
+ path = self.request.path.replace('/docs/latest',
+ '/gs/dartlang-api-docs/' + str(version))
+ else:
+ path = self.request.path.replace('/docs', '/gs/dartlang-api-docs')
+ if path.endswith('/'):
+ path = path + 'index.html'
+ return path
-class DomRedirectPage(webapp2.RequestHandler):
def get(self):
- if self.request.path == '/dom.html':
- self.redirect('/html.html', permanent=True)
- return
+ path = self.resolve_doc_path()
+ gs_key = blobstore.create_gs_key(path)
+ age = self.get_cache_age(path)
+
+ self.response.headers['Cache-Control'] = 'max-age=' + \
+ str(age) + ',s-maxage=' + str(age)
+
+ # is there a better way to check if a file exists in cloud storage?
+ # AE will serve a 500 if the file doesn't exist, but that should
+ # be a 404
+
+ path_exists = memcache.get(path)
+ if path_exists is not None:
+ if path_exists == "1":
+ self.send_blob(gs_key)
+ else:
+ self.error(404)
+ else:
+ try:
+ # just check for existance
+ files.open(path, 'r').close()
+ memcache.add(key=path, value="1", time=ONE_DAY)
+ self.send_blob(gs_key)
+ except files.file.ExistenceError:
+ memcache.add(key=path, value="0", time=ONE_DAY)
+ self.error(404)
+
+ # this doesn't get called, unfortunately.
+ # if this ever starts working, remove the try and files.open
+ # from get, above, and instead retroactively handle a missing file here
+ # def handle_exception(self, exception, debug_mode):
+ # # awful hack for when file in cloud storage doesn't exist
+ # if isinstance(exception, TypeError):
+ # logging.debug('oh noes!')
+ # path = self.resolve_path()
+ # try:
+ # with files.open(path, 'r') as f:
+ # # the file really does exist, so 500 must be something else
+ # self.error(500)
+ # except files.file.ExistenceError:
+ # # file does not exist
+ # self.error(404)
+ # else:
+ # logging.exception(exception)
- url = self.request.path[4:len(self.request.path)]
- self.redirect('/html' + url, permanent=True)
+def redir_to_latest(handler, *args, **kwargs):
+ path = kwargs['path']
+ if re.search(r'^(core|coreimpl|crypto|io|isolate|json|uri|utf|web)', path):
+ return '/docs/latest/dart_' + path
+ else:
+ return '/docs/latest/' + path
-application = webapp2.WSGIApplication(
- [('/dom.*', DomRedirectPage)],
- debug=True)
+def redir_dom(handler, *args, **kwargs):
+ return '/docs/latest/dart_html' + kwargs['path']
+application = WSGIApplication(
+ [
+ Route('/dom<path:.*>', RedirectHandler, defaults={'_uri': redir_dom}),
+ ('/docs.*', ApiDocs),
+ Route('/<path:.*>', RedirectHandler, defaults={'_uri': redir_to_latest})
+ ],
+ debug=True)
« no previous file with comments | « utils/apidoc/app_engine/app.yaml ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698