web/views/apacherewrite.py
changeset 11057 0b59724cb3f2
parent 11052 058bb3dc685f
child 11058 23eb30449fe5
equal deleted inserted replaced
11052:058bb3dc685f 11057:0b59724cb3f2
     1 # copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
       
     2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
       
     3 #
       
     4 # This file is part of CubicWeb.
       
     5 #
       
     6 # CubicWeb is free software: you can redistribute it and/or modify it under the
       
     7 # terms of the GNU Lesser General Public License as published by the Free
       
     8 # Software Foundation, either version 2.1 of the License, or (at your option)
       
     9 # any later version.
       
    10 #
       
    11 # CubicWeb is distributed in the hope that it will be useful, but WITHOUT
       
    12 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
       
    13 # FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
       
    14 # details.
       
    15 #
       
    16 # You should have received a copy of the GNU Lesser General Public License along
       
    17 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
       
    18 """provide class to do Apache rewrite rules'job inside cubicweb (though functionnalities
       
    19 are much more limited for the moment)
       
    20 
       
    21 """
       
    22 
       
    23 __docformat__ = "restructuredtext en"
       
    24 
       
    25 from re import compile
       
    26 
       
    27 from cubicweb.web import Redirect
       
    28 from cubicweb.web.component import Component
       
    29 
       
    30 class RewriteCond(object):
       
    31     def __init__(self, condition, match='host', rules=(), action='rewrite'):
       
    32         self.condition = compile(condition)
       
    33         assert match in ('host', 'path'), match
       
    34         self.match_part = match
       
    35         self.rules = []
       
    36         for rule, replace in rules:
       
    37             rulergx = compile(rule)
       
    38             self.rules.append( (rulergx, replace) )
       
    39         assert action in ('rewrite', 'redirect', 'stop'), action
       
    40         self.process = getattr(self, 'action_%s' % action)
       
    41 
       
    42     def match(self, **kwargs):
       
    43         self._match = self.condition.match(kwargs[self.match_part])
       
    44         return not self._match is None
       
    45 
       
    46     def action_rewrite(self, path):
       
    47         for rgx, replace in self.rules:
       
    48             if not rgx.match(path) is None:
       
    49                 matchdict = self._match.groupdict() or None
       
    50                 if not matchdict is None:
       
    51                     replace = replace % matchdict
       
    52                 return rgx.sub(replace, path)
       
    53         return path
       
    54 
       
    55     def action_redirect(self, path):
       
    56         url = self.action_rewrite(path)
       
    57         raise Redirect(url)
       
    58 
       
    59     def action_stop(self, path):
       
    60         return path
       
    61 
       
    62 
       
    63 class ApacheURLRewrite(Component):
       
    64     """inherit from this class with actual rules to activate apache style rewriting
       
    65 
       
    66     rules should have the form :
       
    67 
       
    68     [('condition pattern 1', [('rule1 pattern', 'replace expression'),
       
    69                               ('rule2 pattern', 'replace expression')],
       
    70      ('condition pattern 2', [('rule1 pattern', 'replace expression'),
       
    71                               ('rule2 pattern', 'replace expression')]
       
    72     ]
       
    73 
       
    74     for instance the equivalent of the following apache rules:
       
    75 
       
    76         RewriteCond %{HTTP_HOST} ^logilab\.fr
       
    77         RewriteRule ^/(.*) http://www.logilab.fr/$1 [L,R=301]
       
    78 
       
    79         RewriteCond %{HTTP_HOST} ^www\.logilab\.fr
       
    80         RewriteRule ^/(.*) http://localhost:8080/$1 [L,P]
       
    81 
       
    82         RewriteCond %{HTTP_HOST} ^(.+)\.logilab\.fr
       
    83         RewriteRule ^/(data/.*) http://localhost:8080/$1 [L,P]
       
    84         RewriteRule ^/(json.*) http://localhost:8080/$1 [L,P]
       
    85         RewriteRule ^/(.*) http://localhost:8080/m_%1/$1 [L,P]
       
    86 
       
    87     could be written (considering that no "host rewritting" is necessary):
       
    88 
       
    89       class MyAppRules(ApacheURLRewrite):
       
    90         rules = [
       
    91           RewriteCond('logilab\.fr', match='host',
       
    92                       rules=[('/(.*)', r'http://www.logilab.fr/\1')],
       
    93                       action='redirect'),
       
    94           RewriteCond('(www)\.logilab\.fr', match='host', action='stop'),
       
    95           RewriteCond('/(data|json)/', match='path', action='stop'),
       
    96           RewriteCond('(?P<cat>.*)\.logilab\.fr', match='host',
       
    97                       rules=[('/(.*)', r'/m_%(cat)s/\1')]),
       
    98         ]
       
    99     """
       
   100     __abstract__ = True
       
   101     __regid__ = 'urlrewriter'
       
   102     rules = []
       
   103 
       
   104     def get_rules(self, req):
       
   105         return self.rules
       
   106 
       
   107     def rewrite(self, host, path, req):
       
   108         for cond in self.get_rules(req):
       
   109             if cond.match(host=host, path=path):
       
   110                 return cond.process(path)
       
   111         return path