redirector.py revision effb81e5f8246d0db0270817048dc992db66e9fb
1eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch# Copyright 2013 The Chromium Authors. All rights reserved. 2eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch# Use of this source code is governed by a BSD-style license that can be 3eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch# found in the LICENSE file. 4eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 5eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochimport posixpath 6eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochfrom urlparse import urlsplit 7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 8eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochfrom file_system import FileNotFoundError 9effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochfrom future import Future 10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass Redirector(object): 120f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) def __init__(self, compiled_fs_factory, file_system): 13eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch self._file_system = file_system 140f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) self._cache = compiled_fs_factory.ForJson(file_system) 15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch def Redirect(self, host, path): 17eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ''' Check if a path should be redirected, first according to host 18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch redirection rules, then from rules in redirects.json files. 19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 20eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Returns the path that should be redirected to, or None if no redirection 21eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch should occur. 22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ''' 23eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return self._RedirectOldHosts(host, path) or self._RedirectFromConfig(path) 24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 25eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch def _RedirectFromConfig(self, url): 26eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ''' Lookup the redirects configuration file in the directory that contains 27eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch the requested resource. If no redirection rule is matched, or no 28eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch configuration file exists, returns None. 29eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ''' 30eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch dirname, filename = posixpath.split(url) 31eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 32eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch try: 33eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch rules = self._cache.GetFromFile( 340f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) posixpath.join(dirname, 'redirects.json')).Get() 35eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch except FileNotFoundError: 36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return None 37eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 38eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch redirect = rules.get(filename) 39eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if redirect is None: 40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return None 41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (redirect.startswith('/') or 42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch urlsplit(redirect).scheme in ('http', 'https')): 43eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return redirect 44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return posixpath.normpath(posixpath.join(dirname, redirect)) 46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch def _RedirectOldHosts(self, host, path): 48eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ''' Redirect paths from the old code.google.com to the new 49eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch developer.chrome.com, retaining elements like the channel and https, if 50eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch used. 51eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ''' 52eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if urlsplit(host).hostname != 'code.google.com': 53eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return None 54eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 55eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch path = path.split('/') 56eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if path and path[0] == 'chrome': 57eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch path.pop(0) 58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return 'https://developer.chrome.com/' + posixpath.join(*path) 60eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch def Cron(self): 62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ''' Load files during a cron run. 63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ''' 64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) futures = [] 650f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) for root, dirs, files in self._file_system.Walk(''): 66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if 'redirects.json' in files: 67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) futures.append( 68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) self._cache.GetFromFile(posixpath.join(root, 'redirects.json'))) 69effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return Future(callback=lambda: [f.Get() for f in futures]) 70