web/views/apacherewrite.py
changeset 0 b97547f5f1fa
child 661 4f61eb8a96b7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/views/apacherewrite.py	Wed Nov 05 15:52:50 2008 +0100
@@ -0,0 +1,94 @@
+"""provide class to do Apache rewrite rules'job inside cubicweb (though functionnalities
+are much more limited for the moment)
+
+:organization: Logilab
+:copyright: 2007-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
+"""
+
+__docformat__ = "restructuredtext en"
+
+from re import compile
+
+from cubicweb.web import Redirect
+from cubicweb.web.component import SingletonComponent
+
+class RewriteCond(object):
+    def __init__(self, condition, match='host', rules=(), action='rewrite'):
+        self.condition = compile(condition)
+        assert match in ('host', 'path'), match
+        self.match_part = match
+        self.rules = []
+        for rule, replace in rules:
+            rulergx = compile(rule)
+            self.rules.append( (rulergx, replace) )
+        assert action in ('rewrite', 'redirect', 'stop'), action
+        self.process = getattr(self, 'action_%s' % action)
+
+    def match(self, **kwargs):
+        self._match = self.condition.match(kwargs[self.match_part])
+        return not self._match is None
+    
+    def action_rewrite(self, path):
+        for rgx, replace in self.rules:
+            if not rgx.match(path) is None:
+                matchdict = self._match.groupdict() or None
+                if not matchdict is None:
+                    replace = replace % matchdict
+                return rgx.sub(replace, path)
+        return path
+
+    def action_redirect(self, path):
+        url = self.action_rewrite(path)
+        raise Redirect(url)
+
+    def action_stop(self, path):
+        return path
+
+    
+class ApacheURLRewrite(SingletonComponent):
+    """inherit from this class with actual rules to activate apache style rewriting
+
+    rules should have the form :
+
+    [('condition pattern 1', [('rule1 pattern', 'replace expression'),
+                              ('rule2 pattern', 'replace expression')],
+     ('condition pattern 2', [('rule1 pattern', 'replace expression'),
+                              ('rule2 pattern', 'replace expression')]
+    ]
+
+    for instance the equivalent of the following apache rules:
+
+        RewriteCond %{HTTP_HOST} ^logilab\.fr
+        RewriteRule ^/(.*) http://www.logilab.fr/$1 [L,R=301]
+
+        RewriteCond %{HTTP_HOST} ^www\.logilab\.fr
+        RewriteRule ^/(.*) http://localhost:8080/$1 [L,P]
+
+        RewriteCond %{HTTP_HOST} ^(.+)\.logilab\.fr
+        RewriteRule ^/(data/.*) http://localhost:8080/$1 [L,P]
+        RewriteRule ^/(json.*) http://localhost:8080/$1 [L,P]
+        RewriteRule ^/(.*) http://localhost:8080/m_%1/$1 [L,P]
+    
+    could be written (considering that no "host rewritting" is necessary):
+
+      class MyAppRules(ApacheURLRewrite): 
+        rules = [
+          RewriteCond('logilab\.fr', match='host',
+                      rules=[('/(.*)', r'http://www.logilab.fr/\1')],
+                      action='redirect'),
+          RewriteCond('(www)\.logilab\.fr', match='host', action='stop'),
+          RewriteCond('/(data|json)/', match='path', action='stop'),
+          RewriteCond('(?P<cat>.*)\.logilab\.fr', match='host', 
+                      rules=[('/(.*)', r'/m_%(cat)s/\1')]),
+        ]
+    """
+    __abstract__ = True
+    id = 'urlrewriter'
+    rules = []
+        
+    def rewrite(self, host, path):
+        for cond in self.rules:
+            if cond.match(host=host, path=path):
+                return cond.process(path)
+        return path