redirector.py revision a36e5920737c6adbddd3e43b760e5de8431db6e0
1# Copyright 2013 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5import posixpath 6from urlparse import urlsplit 7 8from branch_utility import BranchUtility 9from file_system import FileNotFoundError 10from third_party.json_schema_compiler.json_parse import Parse 11 12class Redirector(object): 13 def __init__(self, compiled_fs_factory, file_system, root_path): 14 self._root_path = root_path 15 self._file_system = file_system 16 self._cache = compiled_fs_factory.Create( 17 lambda _, rules: Parse(rules), Redirector) 18 19 def Redirect(self, host, path): 20 ''' Check if a path should be redirected, first according to host 21 redirection rules, then from rules in redirects.json files. 22 23 Returns the path that should be redirected to, or None if no redirection 24 should occur. 25 ''' 26 return self._RedirectOldHosts(host, path) or self._RedirectFromConfig(path) 27 28 def _RedirectFromConfig(self, url): 29 ''' Lookup the redirects configuration file in the directory that contains 30 the requested resource. If no redirection rule is matched, or no 31 configuration file exists, returns None. 32 ''' 33 dirname, filename = posixpath.split(url) 34 35 try: 36 rules = self._cache.GetFromFile( 37 posixpath.join(self._root_path, dirname, 'redirects.json')) 38 except FileNotFoundError: 39 return None 40 41 redirect = rules.get(filename) 42 if redirect is None: 43 return None 44 if (redirect.startswith('/') or 45 urlsplit(redirect).scheme in ('http', 'https')): 46 return redirect 47 48 return posixpath.normpath('/' + posixpath.join(dirname, redirect)) 49 50 def _RedirectOldHosts(self, host, path): 51 ''' Redirect paths from the old code.google.com to the new 52 developer.chrome.com, retaining elements like the channel and https, if 53 used. 54 ''' 55 if urlsplit(host).hostname != 'code.google.com': 56 return None 57 58 path = path.split('/') 59 if path and path[0] == 'chrome': 60 path.pop(0) 61 62 for channel in BranchUtility.GetAllChannelNames(): 63 if channel in path: 64 path.remove(channel) 65 path.insert(0, channel) 66 break 67 68 return 'https://developer.chrome.com/' + posixpath.join(*path) 69 70 def Cron(self): 71 ''' Load files during a cron run. 72 ''' 73 for root, dirs, files in self._file_system.Walk(self._root_path + '/'): 74 if 'redirects.json' in files: 75 self._cache.GetFromFile('%s/redirects.json' % posixpath.join( 76 self._root_path, root)) 77