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

Unified Diff: chrome/common/extensions/docs/server2/handler.py

Issue 14273035: Docserver: refactor the Handler/ServerInstance relationship into a servlet (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: done Created 7 years, 8 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
Index: chrome/common/extensions/docs/server2/handler.py
diff --git a/chrome/common/extensions/docs/server2/handler.py b/chrome/common/extensions/docs/server2/handler.py
index af2682356785cfc3cab939cbf1f47a3c6e1c7bf2..8fd58124cf868e099135171a653940287f412430 100644
--- a/chrome/common/extensions/docs/server2/handler.py
+++ b/chrome/common/extensions/docs/server2/handler.py
@@ -2,164 +2,24 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import logging
-import os
-from StringIO import StringIO
-import traceback
+from appengine_wrappers import webapp
+from cron_servlet import CronServlet
+from render_servlet import RenderServlet
-from appengine_wrappers import (
- DeadlineExceededError, IsDevServer, logservice, memcache, urlfetch, webapp)
-from branch_utility import BranchUtility
-from server_instance import ServerInstance
-import svn_constants
-import time
-
-# The default channel to serve docs for if no channel is specified.
-_DEFAULT_CHANNEL = 'stable'
+_SERVLETS = {
+ 'cron': CronServlet,
+}
class Handler(webapp.RequestHandler):
- # AppEngine instances should never need to call out to SVN. That should only
- # ever be done by the cronjobs, which then write the result into DataStore,
- # which is as far as instances look.
- #
- # Why? SVN is slow and a bit flaky. Cronjobs failing is annoying but
- # temporary. Instances failing affects users, and is really bad.
- #
- # Anyway - to enforce this, we actually don't give instances access to SVN.
- # If anything is missing from datastore, it'll be a 404. If the cronjobs
- # don't manage to catch everything - uhoh. On the other hand, we'll figure it
- # out pretty soon, and it also means that legitimate 404s are caught before a
- # round trip to SVN.
- #
- # However, we can't expect users of preview.py nor the dev server to run a
- # cronjob first, so, this is a hack allow that to be online all of the time.
- # TODO(kalman): achieve this via proper dependency injection.
- ALWAYS_ONLINE = IsDevServer()
-
def __init__(self, request, response):
super(Handler, self).__init__(request, response)
- def _HandleGet(self, path):
- channel_name, real_path = BranchUtility.SplitChannelNameFromPath(path)
-
- if channel_name == _DEFAULT_CHANNEL:
- self.redirect('/%s' % real_path)
- return
-
- if channel_name is None:
- channel_name = _DEFAULT_CHANNEL
-
- # TODO(kalman): Check if |path| is a directory and serve path/index.html
- # rather than special-casing apps/extensions.
- if real_path.strip('/') == 'apps':
- real_path = 'apps/index.html'
- if real_path.strip('/') == 'extensions':
- real_path = 'extensions/index.html'
-
- constructor = (
- ServerInstance.CreateOnline if Handler.ALWAYS_ONLINE else
- ServerInstance.GetOrCreateOffline)
- server_instance = constructor(channel_name)
-
- canonical_path = server_instance.path_canonicalizer.Canonicalize(real_path)
- if real_path != canonical_path:
- self.redirect(canonical_path)
- return
-
- server_instance.Get(real_path, self.request, self.response)
-
- def _HandleCron(self, path):
- # Cron strategy:
- #
- # Find all public template files and static files, and render them. Most of
- # the time these won't have changed since the last cron run, so it's a
- # little wasteful, but hopefully rendering is really fast (if it isn't we
- # have a problem).
- class MockResponse(object):
- def __init__(self):
- self.status = 200
- self.out = StringIO()
- self.headers = {}
- def set_status(self, status):
- self.status = status
- def clear(self, *args):
- pass
-
- class MockRequest(object):
- def __init__(self, path):
- self.headers = {}
- self.path = path
- self.url = '//localhost/%s' % path
-
- channel = path.split('/')[-1]
- logging.info('cron/%s: starting' % channel)
-
- server_instance = ServerInstance.CreateOnline(channel)
-
- def run_cron_for_dir(d, path_prefix=''):
- success = True
- start_time = time.time()
- files = [f for f in server_instance.content_cache.GetFromFileListing(d)
- if not f.endswith('/')]
- logging.info('cron/%s: rendering %s files from %s...' % (
- channel, len(files), d))
- for i, f in enumerate(files):
- error = None
- path = '%s%s' % (path_prefix, f)
- try:
- response = MockResponse()
- server_instance.Get(path, MockRequest(path), response)
- if response.status != 200:
- error = 'Got %s response' % response.status
- except DeadlineExceededError:
- logging.error(
- 'cron/%s: deadline exceeded rendering %s (%s of %s): %s' % (
- channel, path, i + 1, len(files), traceback.format_exc()))
- raise
- except error:
- pass
- if error:
- logging.error('cron/%s: error rendering %s: %s' % (
- channel, path, error))
- success = False
- logging.info('cron/%s: rendering %s files from %s took %s seconds' % (
- channel, len(files), d, time.time() - start_time))
- return success
-
- success = True
- for path, path_prefix in (
- # Note: rendering the public templates will pull in all of the private
- # templates.
- (svn_constants.PUBLIC_TEMPLATE_PATH, ''),
- # Note: rendering the public templates will have pulled in the .js and
- # manifest.json files (for listing examples on the API reference pages),
- # but there are still images, CSS, etc.
- (svn_constants.STATIC_PATH, 'static/'),
- (svn_constants.EXAMPLES_PATH, 'extensions/examples/')):
- try:
- # Note: don't try to short circuit any of this stuff. We want to run
- # the cron for all the directories regardless of intermediate failures.
- success = run_cron_for_dir(path, path_prefix=path_prefix) and success
- except DeadlineExceededError:
- success = False
- break
-
- if success:
- self.response.status = 200
- self.response.out.write('Success')
- else:
- self.response.status = 500
- self.response.out.write('Failure')
-
- logging.info('cron/%s: finished' % channel)
-
def _RedirectSpecialCases(self, path):
- google_dev_url = 'http://developer.google.com/chrome'
- if path == '/' or path == '/index.html':
- self.redirect(google_dev_url)
+ if not path or path == 'index.html':
+ self.redirect('http://developer.google.com/chrome')
return True
- if path == '/apps.html':
+ if path == 'apps.html':
self.redirect('/apps/about_apps.html')
return True
@@ -189,7 +49,9 @@ class Handler(webapp.RequestHandler):
return True
def get(self):
- path = self.request.path
+ path, request, response = (self.request.path.lstrip('/'),
+ self.request,
+ self.response)
if path in ['favicon.ico', 'robots.txt']:
response.set_status(404)
@@ -197,25 +59,25 @@ class Handler(webapp.RequestHandler):
if self._RedirectSpecialCases(path):
return
-
- if path.startswith('/cron'):
- # Crons often time out, and when they do *and* then eventually try to
- # flush logs they die. Turn off autoflush and manually do so at the end.
- logservice.AUTOFLUSH_ENABLED = False
- try:
- self._HandleCron(path)
- finally:
- logservice.flush()
+ if self._RedirectFromCodeDotGoogleDotCom(path):
return
- # Redirect paths like "directory" to "directory/". This is so relative
- # file paths will know to treat this as a directory.
- if os.path.splitext(path)[1] == '' and path[-1] != '/':
- self.redirect(path + '/')
- return
+ if path.startswith('_'):
+ servlet_path = path[1:]
+ if servlet_path.find('/') == -1:
+ servlet_path += '/'
+ servlet_name, servlet_path = servlet_path.split('/', 1)
+ servlet = _SERVLETS.get(servlet_name)
+ if servlet is None:
+ response.out.write('"%s" servlet not found' % servlet_path)
+ response.set_status(404)
+ return
+ else:
+ servlet_path = path
+ servlet = RenderServlet
- path = path.strip('/')
- if self._RedirectFromCodeDotGoogleDotCom(path):
- return
+ servlet_response = servlet(servlet_path, request.headers).Get()
- self._HandleGet(path)
+ response.out.write(servlet_response.content.ToString())
+ response.headers.update(servlet_response.headers)
+ response.status = servlet_response.status
« no previous file with comments | « chrome/common/extensions/docs/server2/cron_servlet.py ('k') | chrome/common/extensions/docs/server2/integration_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698