redirector.py revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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 file_system import FileNotFoundError 9from future import Gettable, Future 10 11class Redirector(object): 12 def __init__(self, compiled_fs_factory, file_system): 13 self._file_system = file_system 14 self._cache = compiled_fs_factory.ForJson(file_system) 15 16 def Redirect(self, host, path): 17 ''' Check if a path should be redirected, first according to host 18 redirection rules, then from rules in redirects.json files. 19 20 Returns the path that should be redirected to, or None if no redirection 21 should occur. 22 ''' 23 return self._RedirectOldHosts(host, path) or self._RedirectFromConfig(path) 24 25 def _RedirectFromConfig(self, url): 26 ''' Lookup the redirects configuration file in the directory that contains 27 the requested resource. If no redirection rule is matched, or no 28 configuration file exists, returns None. 29 ''' 30 dirname, filename = posixpath.split(url) 31 32 try: 33 rules = self._cache.GetFromFile( 34 posixpath.join(dirname, 'redirects.json')).Get() 35 except FileNotFoundError: 36 return None 37 38 redirect = rules.get(filename) 39 if redirect is None: 40 return None 41 if (redirect.startswith('/') or 42 urlsplit(redirect).scheme in ('http', 'https')): 43 return redirect 44 45 return posixpath.normpath(posixpath.join(dirname, redirect)) 46 47 def _RedirectOldHosts(self, host, path): 48 ''' Redirect paths from the old code.google.com to the new 49 developer.chrome.com, retaining elements like the channel and https, if 50 used. 51 ''' 52 if urlsplit(host).hostname != 'code.google.com': 53 return None 54 55 path = path.split('/') 56 if path and path[0] == 'chrome': 57 path.pop(0) 58 59 return 'https://developer.chrome.com/' + posixpath.join(*path) 60 61 def Cron(self): 62 ''' Load files during a cron run. 63 ''' 64 futures = [] 65 for root, dirs, files in self._file_system.Walk(''): 66 if 'redirects.json' in files: 67 futures.append( 68 self._cache.GetFromFile(posixpath.join(root, 'redirects.json'))) 69 return Future(delegate=Gettable(lambda: [f.Get() for f in futures])) 70