| OLD | NEW |
| 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 import logging | 5 import logging |
| 6 import os | 6 import os |
| 7 from StringIO import StringIO | 7 from StringIO import StringIO |
| 8 | 8 |
| 9 from appengine_wrappers import webapp | 9 from appengine_wrappers import webapp |
| 10 from appengine_wrappers import memcache | 10 from appengine_wrappers import memcache |
| 11 from appengine_wrappers import urlfetch | 11 from appengine_wrappers import urlfetch |
| 12 from branch_utility import BranchUtility | 12 from branch_utility import BranchUtility |
| 13 from server_instance import ServerInstance | 13 from server_instance import ServerInstance |
| 14 import svn_constants | 14 import svn_constants |
| 15 import time | 15 import time |
| 16 | 16 |
| 17 # The default channel to serve docs for if no channel is specified. | 17 # The default channel to serve docs for if no channel is specified. |
| 18 _DEFAULT_CHANNEL = 'stable' | 18 _DEFAULT_CHANNEL = 'stable' |
| 19 | 19 |
| 20 class Handler(webapp.RequestHandler): | 20 class Handler(webapp.RequestHandler): |
| 21 # HACK: for preview.py. |
| 22 # TODO(kalman): achieve this via proper dependency injection. |
| 23 ALWAYS_ONLINE = False |
| 24 |
| 21 def __init__(self, request, response): | 25 def __init__(self, request, response): |
| 22 super(Handler, self).__init__(request, response) | 26 super(Handler, self).__init__(request, response) |
| 23 | 27 |
| 24 def _HandleGet(self, path): | 28 def _HandleGet(self, path): |
| 25 channel_name, real_path = BranchUtility.SplitChannelNameFromPath(path) | 29 channel_name, real_path = BranchUtility.SplitChannelNameFromPath(path) |
| 26 | 30 |
| 27 if channel_name == _DEFAULT_CHANNEL: | 31 if channel_name == _DEFAULT_CHANNEL: |
| 28 self.redirect('/%s' % real_path) | 32 self.redirect('/%s' % real_path) |
| 29 return | 33 return |
| 30 | 34 |
| 31 if channel_name is None: | 35 if channel_name is None: |
| 32 channel_name = _DEFAULT_CHANNEL | 36 channel_name = _DEFAULT_CHANNEL |
| 33 | 37 |
| 34 # TODO(kalman): Check if |path| is a directory and serve path/index.html | 38 # TODO(kalman): Check if |path| is a directory and serve path/index.html |
| 35 # rather than special-casing apps/extensions. | 39 # rather than special-casing apps/extensions. |
| 36 if real_path.strip('/') == 'apps': | 40 if real_path.strip('/') == 'apps': |
| 37 real_path = 'apps/index.html' | 41 real_path = 'apps/index.html' |
| 38 if real_path.strip('/') == 'extensions': | 42 if real_path.strip('/') == 'extensions': |
| 39 real_path = 'extensions/index.html' | 43 real_path = 'extensions/index.html' |
| 40 | 44 |
| 41 server_instance = ServerInstance.GetOrCreate(channel_name) | 45 constructor = ( |
| 46 ServerInstance.GetOrCreateOnline if Handler.ALWAYS_ONLINE else |
| 47 ServerInstance.GetOrCreateOffline) |
| 48 server_instance = constructor(channel_name) |
| 42 | 49 |
| 43 canonical_path = server_instance.path_canonicalizer.Canonicalize(real_path) | 50 canonical_path = server_instance.path_canonicalizer.Canonicalize(real_path) |
| 44 if real_path != canonical_path: | 51 if real_path != canonical_path: |
| 45 self.redirect(canonical_path) | 52 self.redirect(canonical_path) |
| 46 return | 53 return |
| 47 | 54 |
| 48 ServerInstance.GetOrCreate(channel_name).Get(real_path, | 55 server_instance.Get(real_path, self.request, self.response) |
| 49 self.request, | |
| 50 self.response) | |
| 51 | 56 |
| 52 def _HandleCron(self, path): | 57 def _HandleCron(self, path): |
| 53 # Cron strategy: | 58 # Cron strategy: |
| 54 # | 59 # |
| 55 # Find all public template files and static files, and render them. Most of | 60 # Find all public template files and static files, and render them. Most of |
| 56 # the time these won't have changed since the last cron run, so it's a | 61 # the time these won't have changed since the last cron run, so it's a |
| 57 # little wasteful, but hopefully rendering is really fast (if it isn't we | 62 # little wasteful, but hopefully rendering is really fast (if it isn't we |
| 58 # have a problem). | 63 # have a problem). |
| 59 class MockResponse(object): | 64 class MockResponse(object): |
| 60 def __init__(self): | 65 def __init__(self): |
| 61 self.status = 200 | 66 self.status = 200 |
| 62 self.out = StringIO() | 67 self.out = StringIO() |
| 63 self.headers = {} | 68 self.headers = {} |
| 64 def set_status(self, status): | 69 def set_status(self, status): |
| 65 self.status = status | 70 self.status = status |
| 66 def clear(self, *args): | 71 def clear(self, *args): |
| 67 pass | 72 pass |
| 68 | 73 |
| 69 class MockRequest(object): | 74 class MockRequest(object): |
| 70 def __init__(self, path): | 75 def __init__(self, path): |
| 71 self.headers = {} | 76 self.headers = {} |
| 72 self.path = path | 77 self.path = path |
| 73 self.url = '//localhost/%s' % path | 78 self.url = '//localhost/%s' % path |
| 74 | 79 |
| 75 channel = path.split('/')[-1] | 80 channel = path.split('/')[-1] |
| 76 logging.info('cron/%s: starting' % channel) | 81 logging.info('cron/%s: starting' % channel) |
| 77 | 82 |
| 78 server_instance = ServerInstance.GetOrCreate(channel) | 83 server_instance = ServerInstance.GetOrCreateOnline(channel) |
| 79 | 84 |
| 80 def run_cron_for_dir(d): | 85 def run_cron_for_dir(d, path_prefix=''): |
| 81 error = None | 86 error = None |
| 82 start_time = time.time() | 87 start_time = time.time() |
| 83 files = [f for f in server_instance.content_cache.GetFromFileListing(d) | 88 files = [f for f in server_instance.content_cache.GetFromFileListing(d) |
| 84 if not f.endswith('/')] | 89 if not f.endswith('/')] |
| 85 for f in files: | 90 for f in files: |
| 91 path = '%s%s' % (path_prefix, f) |
| 86 try: | 92 try: |
| 87 server_instance.Get(f, MockRequest(f), MockResponse()) | 93 response = MockResponse() |
| 94 server_instance.Get(path, MockRequest(path), response) |
| 95 if response.status != 200: |
| 96 error = 'Got %s response' % response.status |
| 88 except error: | 97 except error: |
| 89 logging.error('cron/%s: error rendering %s/%s: %s' % ( | 98 pass |
| 90 channel, d, f, error)) | 99 if error: |
| 91 logging.info('cron/%s: rendering %s files in %s took %s seconds' % ( | 100 logging.error('cron/%s: error rendering %s: %s' % ( |
| 92 channel, len(files), d, time.time() - start_time)) | 101 channel, path, error)) |
| 102 logging.info('cron/%s: rendering %s files took %s seconds' % ( |
| 103 channel, len(files), time.time() - start_time)) |
| 93 return error | 104 return error |
| 94 | 105 |
| 95 # Don't use "or" since we want to evaluate everything no matter what. | 106 # Don't use "or" since we want to evaluate everything no matter what. |
| 96 was_error = any((run_cron_for_dir(svn_constants.PUBLIC_TEMPLATE_PATH), | 107 was_error = any(( |
| 97 run_cron_for_dir(svn_constants.STATIC_PATH))) | 108 run_cron_for_dir(svn_constants.PUBLIC_TEMPLATE_PATH), |
| 109 run_cron_for_dir(svn_constants.STATIC_PATH, path_prefix='static/'))) |
| 98 | 110 |
| 99 if was_error: | 111 if was_error: |
| 100 self.response.status = 500 | 112 self.response.status = 500 |
| 101 self.response.out.write('Failure') | 113 self.response.out.write('Failure') |
| 102 else: | 114 else: |
| 103 self.response.status = 200 | 115 self.response.status = 200 |
| 104 self.response.out.write('Success') | 116 self.response.out.write('Success') |
| 105 | 117 |
| 106 logging.info('cron/%s: finished' % channel) | 118 logging.info('cron/%s: finished' % channel) |
| 107 | 119 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 153 # file paths will know to treat this as a directory. | 165 # file paths will know to treat this as a directory. |
| 154 if os.path.splitext(path)[1] == '' and path[-1] != '/': | 166 if os.path.splitext(path)[1] == '' and path[-1] != '/': |
| 155 self.redirect(path + '/') | 167 self.redirect(path + '/') |
| 156 return | 168 return |
| 157 | 169 |
| 158 path = path.strip('/') | 170 path = path.strip('/') |
| 159 if self._RedirectFromCodeDotGoogleDotCom(path): | 171 if self._RedirectFromCodeDotGoogleDotCom(path): |
| 160 return | 172 return |
| 161 | 173 |
| 162 self._HandleGet(path) | 174 self._HandleGet(path) |
| OLD | NEW |