[Checkins] SVN: hurry.resource/branches/janjaapdriessen-resource-publisher/src/hurry/resource/ split resource publisher from the delegator functionality "middleware"

Jan-Wijbrand Kolman janwijbrand at gmail.com
Tue Nov 23 11:16:57 EST 2010


Log message for revision 118537:
  split resource publisher from the delegator functionality "middleware"

Changed:
  U   hurry.resource/branches/janjaapdriessen-resource-publisher/src/hurry/resource/README.txt
  U   hurry.resource/branches/janjaapdriessen-resource-publisher/src/hurry/resource/__init__.py
  U   hurry.resource/branches/janjaapdriessen-resource-publisher/src/hurry/resource/core.py
  U   hurry.resource/branches/janjaapdriessen-resource-publisher/src/hurry/resource/publisher.py

-=-
Modified: hurry.resource/branches/janjaapdriessen-resource-publisher/src/hurry/resource/README.txt
===================================================================
--- hurry.resource/branches/janjaapdriessen-resource-publisher/src/hurry/resource/README.txt	2010-11-23 16:14:07 UTC (rev 118536)
+++ hurry.resource/branches/janjaapdriessen-resource-publisher/src/hurry/resource/README.txt	2010-11-23 16:16:56 UTC (rev 118537)
@@ -753,9 +753,9 @@
 for instance)::
 
   >>> print needed.render()
-  <link rel="stylesheet" type="text/css" href="http://localhost/static/:hash:.../foo/b.css" />
-  <script type="text/javascript" src="http://localhost/static/:hash:.../foo/a.js"></script>
-  <script type="text/javascript" src="http://localhost/static/:hash:.../foo/c.js"></script>
+  <link rel="stylesheet" type="text/css" href="http://localhost/static/fanstatic/:hash:.../foo/b.css" />
+  <script type="text/javascript" src="http://localhost/static/fanstatic/:hash:.../foo/a.js"></script>
+  <script type="text/javascript" src="http://localhost/static/fanstatic/:hash:.../foo/c.js"></script>
 
 Let's set this a currently needed inclusions::
 
@@ -766,9 +766,9 @@
 
   >>> from hurry import resource
   >>> print resource.render()
-  <link rel="stylesheet" type="text/css" href="http://localhost/static/:hash:.../foo/b.css" />
-  <script type="text/javascript" src="http://localhost/static/:hash:.../foo/a.js"></script>
-  <script type="text/javascript" src="http://localhost/static/:hash:.../foo/c.js"></script>
+  <link rel="stylesheet" type="text/css" href="http://localhost/static/fanstatic/:hash:.../foo/b.css" />
+  <script type="text/javascript" src="http://localhost/static/fanstatic/:hash:.../foo/a.js"></script>
+  <script type="text/javascript" src="http://localhost/static/fanstatic/:hash:.../foo/c.js"></script>
 
 Hashing resources
 =================
@@ -786,12 +786,12 @@
 To make browsers update their caches of resources immediately when the
 resource changes, the absolute URLs of resources can now be made to contain a
 hash of the resource's contents, so it will look like
-/foo/:hash:12345/myresource instead of /foo/myresource.
+/foo/fanstatic/:hash:12345/myresource instead of /foo/myresource.
 
   >>> print resource.render()
-  <link rel="stylesheet" type="text/css" href="http://localhost/static/:hash:.../foo/b.css" />
-  <script type="text/javascript" src="http://localhost/static/:hash:.../foo/a.js"></script>
-  <script type="text/javascript" src="http://localhost/static/:hash:.../foo/c.js"></script>
+  <link rel="stylesheet" type="text/css" href="http://localhost/static/fanstatic/:hash:.../foo/b.css" />
+  <script type="text/javascript" src="http://localhost/static/fanstatic/:hash:.../foo/a.js"></script>
+  <script type="text/javascript" src="http://localhost/static/fanstatic/:hash:.../foo/c.js"></script>
 
 More about the devmode in a minute::
 
@@ -871,9 +871,9 @@
 
   >>> print needed.render_into_html(html)
   <html><head>
-      <link rel="stylesheet" type="text/css" href="http://localhost/static/:hash:.../foo/b.css" />
-  <script type="text/javascript" src="http://localhost/static/:hash:.../foo/a.js"></script>
-  <script type="text/javascript" src="http://localhost/static/:hash:.../foo/c.js"></script>
+      <link rel="stylesheet" type="text/css" href="http://localhost/static/fanstatic/:hash:.../foo/b.css" />
+  <script type="text/javascript" src="http://localhost/static/fanstatic/:hash:.../foo/a.js"></script>
+  <script type="text/javascript" src="http://localhost/static/fanstatic/:hash:.../foo/c.js"></script>
   something more</head></html>
 
 The top-level convenience function does this for the currently needed
@@ -881,9 +881,9 @@
 
   >>> print resource.render_into_html(html)
   <html><head>
-      <link rel="stylesheet" type="text/css" href="http://localhost/static/:hash:.../foo/b.css" />
-  <script type="text/javascript" src="http://localhost/static/:hash:.../foo/a.js"></script>
-  <script type="text/javascript" src="http://localhost/static/:hash:.../foo/c.js"></script>
+      <link rel="stylesheet" type="text/css" href="http://localhost/static/fanstatic/:hash:.../foo/b.css" />
+  <script type="text/javascript" src="http://localhost/static/fanstatic/:hash:.../foo/a.js"></script>
+  <script type="text/javascript" src="http://localhost/static/fanstatic/:hash:.../foo/c.js"></script>
   something more</head></html>
 
 See below for a way to insert into HTML when bottom fragments are
@@ -904,9 +904,9 @@
 
   >>> top, bottom = needed.render_topbottom()
   >>> print top
-  <link rel="stylesheet" type="text/css" href="http://localhost/static/:hash:.../foo/b.css" />
-  <script type="text/javascript" src="http://localhost/static/:hash:.../foo/a.js"></script>
-  <script type="text/javascript" src="http://localhost/static/:hash:.../foo/c.js"></script>
+  <link rel="stylesheet" type="text/css" href="http://localhost/static/fanstatic/:hash:.../foo/b.css" />
+  <script type="text/javascript" src="http://localhost/static/fanstatic/:hash:.../foo/a.js"></script>
+  <script type="text/javascript" src="http://localhost/static/fanstatic/:hash:.../foo/c.js"></script>
   >>> print bottom
   <BLANKLINE>
 
@@ -921,9 +921,9 @@
 
   >>> top, bottom = needed.render_topbottom()
   >>> print top
-  <link rel="stylesheet" type="text/css" href="http://localhost/static/:hash:.../foo/b.css" />
-  <script type="text/javascript" src="http://localhost/static/:hash:.../foo/a.js"></script>
-  <script type="text/javascript" src="http://localhost/static/:hash:.../foo/c.js"></script>
+  <link rel="stylesheet" type="text/css" href="http://localhost/static/fanstatic/:hash:.../foo/b.css" />
+  <script type="text/javascript" src="http://localhost/static/fanstatic/:hash:.../foo/a.js"></script>
+  <script type="text/javascript" src="http://localhost/static/fanstatic/:hash:.../foo/c.js"></script>
   >>> print bottom
   <BLANKLINE>
 
@@ -933,10 +933,10 @@
   >>> needed.bottom(force=True)
   >>> top, bottom = needed.render_topbottom()
   >>> print top
-  <link rel="stylesheet" type="text/css" href="http://localhost/static/:hash:.../foo/b.css" />
+  <link rel="stylesheet" type="text/css" href="http://localhost/static/fanstatic/:hash:.../foo/b.css" />
   >>> print bottom
-  <script type="text/javascript" src="http://localhost/static/:hash:.../foo/a.js"></script>
-  <script type="text/javascript" src="http://localhost/static/:hash:.../foo/c.js"></script>
+  <script type="text/javascript" src="http://localhost/static/fanstatic/:hash:.../foo/a.js"></script>
+  <script type="text/javascript" src="http://localhost/static/fanstatic/:hash:.../foo/c.js"></script>
 
 Let's now introduce a javascript resource that says it is safe to be
 included on the bottom::
@@ -953,10 +953,10 @@
 
   >>> top, bottom = needed.render_topbottom()
   >>> print top
-  <link rel="stylesheet" type="text/css" href="http://localhost/static/:hash:.../foo/b.css" />
-  <script type="text/javascript" src="http://localhost/static/:hash:.../foo/a.js"></script>
-  <script type="text/javascript" src="http://localhost/static/:hash:.../foo/c.js"></script>
-  <script type="text/javascript" src="http://localhost/static/:hash:.../foo/y2.js"></script>
+  <link rel="stylesheet" type="text/css" href="http://localhost/static/fanstatic/:hash:.../foo/b.css" />
+  <script type="text/javascript" src="http://localhost/static/fanstatic/:hash:.../foo/a.js"></script>
+  <script type="text/javascript" src="http://localhost/static/fanstatic/:hash:.../foo/c.js"></script>
+  <script type="text/javascript" src="http://localhost/static/fanstatic/:hash:.../foo/y2.js"></script>
   >>> print bottom
   <BLANKLINE>
 
@@ -968,22 +968,22 @@
 
   >>> top, bottom = needed.render_topbottom()
   >>> print top
-  <link rel="stylesheet" type="text/css" href="http://localhost/static/:hash:.../foo/b.css" />
-  <script type="text/javascript" src="http://localhost/static/:hash:.../foo/a.js"></script>
-  <script type="text/javascript" src="http://localhost/static/:hash:.../foo/c.js"></script>
+  <link rel="stylesheet" type="text/css" href="http://localhost/static/fanstatic/:hash:.../foo/b.css" />
+  <script type="text/javascript" src="http://localhost/static/fanstatic/:hash:.../foo/a.js"></script>
+  <script type="text/javascript" src="http://localhost/static/fanstatic/:hash:.../foo/c.js"></script>
   >>> print bottom
-  <script type="text/javascript" src="http://localhost/static/:hash:.../foo/y2.js"></script>
+  <script type="text/javascript" src="http://localhost/static/fanstatic/:hash:.../foo/y2.js"></script>
 
 There's also a convenience function for the currently needed inclusion::
 
   >>> request.needed = needed
   >>> top, bottom = resource.render_topbottom()
   >>> print top
-  <link rel="stylesheet" type="text/css" href="http://localhost/static/:hash:.../foo/b.css" />
-  <script type="text/javascript" src="http://localhost/static/:hash:.../foo/a.js"></script>
-  <script type="text/javascript" src="http://localhost/static/:hash:.../foo/c.js"></script>
+  <link rel="stylesheet" type="text/css" href="http://localhost/static/fanstatic/:hash:.../foo/b.css" />
+  <script type="text/javascript" src="http://localhost/static/fanstatic/:hash:.../foo/a.js"></script>
+  <script type="text/javascript" src="http://localhost/static/fanstatic/:hash:.../foo/c.js"></script>
   >>> print bottom
-  <script type="text/javascript" src="http://localhost/static/:hash:.../foo/y2.js"></script>
+  <script type="text/javascript" src="http://localhost/static/fanstatic/:hash:.../foo/y2.js"></script>
 
 When we force bottom rendering of Javascript, there is no effect of
 making a resource bottom-safe: all ``.js`` resources will be rendered
@@ -992,11 +992,11 @@
   >>> needed.bottom(force=True)
   >>> top, bottom = needed.render_topbottom()
   >>> print top
-  <link rel="stylesheet" type="text/css" href="http://localhost/static/:hash:.../foo/b.css" />
+  <link rel="stylesheet" type="text/css" href="http://localhost/static/fanstatic/:hash:.../foo/b.css" />
   >>> print bottom
-  <script type="text/javascript" src="http://localhost/static/:hash:.../foo/a.js"></script>
-  <script type="text/javascript" src="http://localhost/static/:hash:.../foo/c.js"></script>
-  <script type="text/javascript" src="http://localhost/static/:hash:.../foo/y2.js"></script>
+  <script type="text/javascript" src="http://localhost/static/fanstatic/:hash:.../foo/a.js"></script>
+  <script type="text/javascript" src="http://localhost/static/fanstatic/:hash:.../foo/c.js"></script>
+  <script type="text/javascript" src="http://localhost/static/fanstatic/:hash:.../foo/y2.js"></script>
 
 Note that if ``bottom`` is enabled, it makes no sense to have a
 resource inclusion ``b`` that depends on a resource inclusion ``a``
@@ -1027,20 +1027,20 @@
 
   >>> print needed.render_topbottom_into_html(html)
   <html><head>
-      <link rel="stylesheet" type="text/css" href="http://localhost/static/:hash:.../foo/b.css" />
-  rest of head</head><body>rest of body<script type="text/javascript" src="http://localhost/static/:hash:.../foo/a.js"></script>
-  <script type="text/javascript" src="http://localhost/static/:hash:.../foo/c.js"></script>
-  <script type="text/javascript" src="http://localhost/static/:hash:.../foo/y2.js"></script></body></html>
+      <link rel="stylesheet" type="text/css" href="http://localhost/static/fanstatic/:hash:.../foo/b.css" />
+  rest of head</head><body>rest of body<script type="text/javascript" src="http://localhost/static/fanstatic/:hash:.../foo/a.js"></script>
+  <script type="text/javascript" src="http://localhost/static/fanstatic/:hash:.../foo/c.js"></script>
+  <script type="text/javascript" src="http://localhost/static/fanstatic/:hash:.../foo/y2.js"></script></body></html>
 
 There's also a function available to do this for the currently needed
 resources::
 
   >>> print resource.render_topbottom_into_html(html)
   <html><head>
-      <link rel="stylesheet" type="text/css" href="http://localhost/static/:hash:.../foo/b.css" />
-  rest of head</head><body>rest of body<script type="text/javascript" src="http://localhost/static/:hash:.../foo/a.js"></script>
-  <script type="text/javascript" src="http://localhost/static/:hash:.../foo/c.js"></script>
-  <script type="text/javascript" src="http://localhost/static/:hash:.../foo/y2.js"></script></body></html>
+      <link rel="stylesheet" type="text/css" href="http://localhost/static/fanstatic/:hash:.../foo/b.css" />
+  rest of head</head><body>rest of body<script type="text/javascript" src="http://localhost/static/fanstatic/:hash:.../foo/a.js"></script>
+  <script type="text/javascript" src="http://localhost/static/fanstatic/:hash:.../foo/c.js"></script>
+  <script type="text/javascript" src="http://localhost/static/fanstatic/:hash:.../foo/y2.js"></script></body></html>
 
 Using WSGI middleware to insert into HTML
 =========================================
@@ -1075,9 +1075,9 @@
 
   >>> print res.body
   <html><head>
-      <link rel="stylesheet" type="text/css" href="http://localhost/static/:hash:.../foo/b.css" />
-  <script type="text/javascript" src="http://localhost/static/:hash:.../foo/a.js"></script>
-  <script type="text/javascript" src="http://localhost/static/:hash:.../foo/c.js"></script>
+      <link rel="stylesheet" type="text/css" href="http://localhost/static/fanstatic/:hash:.../foo/b.css" />
+  <script type="text/javascript" src="http://localhost/static/fanstatic/:hash:.../foo/a.js"></script>
+  <script type="text/javascript" src="http://localhost/static/fanstatic/:hash:.../foo/c.js"></script>
   </head><body</body></html>
 
 When we set the response Content-Type to non-HTML, the middleware
@@ -1111,7 +1111,7 @@
   >>> c.base_url = 'http://localhost/static'
   >>> top, bottom = c.render_topbottom()
   >>> print top
-  <script type="text/javascript" src="http://localhost/static/:hash:.../foo/l1.js"></script>
+  <script type="text/javascript" src="http://localhost/static/fanstatic/:hash:.../foo/l1.js"></script>
   >>> print bottom
   <BLANKLINE>
 
@@ -1127,7 +1127,7 @@
   >>> print top
   <BLANKLINE>
   >>> print bottom
-  <script type="text/javascript" src="http://localhost/static/:hash:.../foo/l1.js"></script>
+  <script type="text/javascript" src="http://localhost/static/fanstatic/:hash:.../foo/l1.js"></script>
 
 Generating resource code
 ========================
@@ -1250,7 +1250,7 @@
   ...     return '<link rel="unknown" href="%s" />' % url
   >>> inclusion_renderers['.unknown'] = render_unknown
   >>> needed.render()
-  '<link rel="unknown" href="http://localhost/static/:hash:.../foo/nothing.unknown" />'
+  '<link rel="unknown" href="http://localhost/static/fanstatic/:hash:.../foo/nothing.unknown" />'
 
 Resource publisher
 ==================
@@ -1261,10 +1261,7 @@
   >>> from hurry.resource.publisher import Publisher
   >>> from paste.fixture import TestApp
   >>> from paste.httpexceptions import HTTPNotFound
-  >>> class NoFindNoResource(object):
-  ... 	    def __call__(self, environ, start_response):
-  ...	    	return HTTPNotFound()(environ, start_response)
-  >>> app = TestApp(Publisher(NoFindNoResource()))
+  >>> app = TestApp(Publisher())
 
 We don't do anything fancy if the resource can not be found, but raise 404.
 
@@ -1284,6 +1281,15 @@
   >>> 'ETag' in headers
   True
 
+  >>> res = app.get('/foo/style.css')
+  >>> print res.body
+  body {
+    color: #f00;
+  }
+  >>> headers = dict(res.headers)
+  >>> 'ETag' in headers
+  True
+
 When we find the 'hash' marker in the requested URL, we send headers that let
 the user agent cache the resources for a long time.
 
@@ -1294,7 +1300,7 @@
 
 We don't set cache-control headers on non-successful responses::
 
-  >>> res = app.get('/:hash:12345/foo/notfound.css', expect_errors=True)
+  >>> res = app.get('/fanstatic/:hash:12345/foo/notfound.css', expect_errors=True)
   >>> headers = dict(res.headers)
   >>> 'Expires' in headers
   False
@@ -1303,13 +1309,13 @@
 
 Hidden files and directories are not served:
 
-  >>> res = app.get('/:hash:foo/sub/.svn/test', expect_errors=True)
+  >>> res = app.get('/fanstatic/:hash:foo/sub/.svn/test', expect_errors=True)
   >>> print res.status
   404
 
 The publisher_signature can be found arbitrarily deep in the path_info:
 
-  >>> res = app.get('/++skin++foo/++etc++bar/foo/:hash:12345/foo/style.css')
+  >>> res = app.get('/++skin++foo/++etc++bar/foo/fanstatic/:hash:12345/foo/style.css')
   >>> res.status
   200
   >>> print res.body

Modified: hurry.resource/branches/janjaapdriessen-resource-publisher/src/hurry/resource/__init__.py
===================================================================
--- hurry.resource/branches/janjaapdriessen-resource-publisher/src/hurry/resource/__init__.py	2010-11-23 16:14:07 UTC (rev 118536)
+++ hurry.resource/branches/janjaapdriessen-resource-publisher/src/hurry/resource/__init__.py	2010-11-23 16:16:56 UTC (rev 118537)
@@ -15,7 +15,7 @@
 from hurry.resource.core import (register_plugin,
                                  get_current_needed_inclusions)
 
-publisher_signature = ':hash:'
+publisher_signature = 'fanstatic'
 
 devmode = False
 

Modified: hurry.resource/branches/janjaapdriessen-resource-publisher/src/hurry/resource/core.py
===================================================================
--- hurry.resource/branches/janjaapdriessen-resource-publisher/src/hurry/resource/core.py	2010-11-23 16:14:07 UTC (rev 118536)
+++ hurry.resource/branches/janjaapdriessen-resource-publisher/src/hurry/resource/core.py	2010-11-23 16:16:56 UTC (rev 118537)
@@ -24,7 +24,8 @@
         # before or (2) we are in development mode.
         if self._signature is None or hurry.resource.devmode:
             self._signature = hurry.resource.hash.checksum(self.path)
-        return hurry.resource.publisher_signature + str(self._signature)
+        return '%s/:hash:%s' % (
+            hurry.resource.publisher_signature, str(self._signature))
 
 # total hack to be able to get the dir the resources will be in
 def caller_dir():

Modified: hurry.resource/branches/janjaapdriessen-resource-publisher/src/hurry/resource/publisher.py
===================================================================
--- hurry.resource/branches/janjaapdriessen-resource-publisher/src/hurry/resource/publisher.py	2010-11-23 16:14:07 UTC (rev 118536)
+++ hurry.resource/branches/janjaapdriessen-resource-publisher/src/hurry/resource/publisher.py	2010-11-23 16:16:56 UTC (rev 118537)
@@ -7,7 +7,6 @@
 
 import hurry.resource
 
-
 class FilterHiddenDirectoryApp(DirectoryApp):
     def __call__(self, environ, start_response):
         path_info = environ['PATH_INFO']
@@ -16,43 +15,60 @@
                 return HTTPNotFound()(environ, start_response)
         return DirectoryApp.__call__(self, environ, start_response)
 
-
 class Publisher(object):
     
-    def __init__(self, app):
-        self._wrapped_app = app
+    def __init__(self):
         self.directory_apps = {}
         for library in hurry.resource.libraries():
             app = FilterHiddenDirectoryApp(library.path)
             self.directory_apps[library.name] = app
 
     def __call__(self, environ, start_response):
+        # Pop the hash, if it exists.
         path_info = environ['PATH_INFO']
+        if path_info.startswith('/:hash:'):
+            path_info_pop(environ)
+            # Overwrite the start_response callable with one that will
+            # apply expiry headers for 20* responses.
+            _start_response = start_response
+            def start_response(status, headers, exc_info=None):
+                # Only set the cache control for succesful requests
+                # (200, 206).
+                if status.startswith('20'):
+                    expires = CACHE_CONTROL.apply(
+                        headers, max_age=10*CACHE_CONTROL.ONE_YEAR)
+                    EXPIRES.update(headers, delta=expires)
+                return _start_response(status, headers, exc_info)
+            
+        # Pop first name, being library name.
+        library_name = path_info_pop(environ)
+        directory_app = self.directory_apps.get(library_name)
+        if directory_app is None:
+            return HTTPNotFound()(environ, start_response)
+        return directory_app(environ, start_response)
 
-        path_segments = [s for s in path_info.split('/') if s.strip() != '']
+class Delegator(object):
+    
+    def __init__(self, app):
+        self.application = app
+        self.resource_publisher = Publisher()
 
-        def hash_find(segment):
-            return not segment.startswith(hurry.resource.publisher_signature)
+    def __call__(self, environ, start_response):
+        path_info = environ['PATH_INFO']
+        trigger = '/%s/' % hurry.resource.publisher_signature
+        chunks = path_info.split(trigger, 1)
+        if len(chunks) == 1:
+            # The trigger is not in the URL at all, we delegate to the
+            # original application.
+            return self.application(environ, start_response) 
+        environ = environ.copy()
+        environ['PATH_INFO'] = '/%s' % chunks[1]
+        return self.resource_publisher(environ, start_response)
 
-        new_path = list(dropwhile(hash_find, path_segments))
+def make_delegator(app, global_conf):
+    return Delegator(app)
 
-        if len(new_path) == 0:
-            # There's no hash signature found in the path, so we
-            # cannot publish it from here. Leave the response to the
-            # wrapped app.
-            return self._wrapped_app(environ, start_response)
-
-        try:
-            hash = new_path.pop(0)
-            library_name = new_path.pop(0)
-        except IndexError:
-            return HTTPNotFound()(environ, start_response)
-
-        try:
-            directory_app = self.directory_apps[library_name]
-        except KeyError:
-            return HTTPNotFound()(environ, start_response)
-
+"""
         def cache_header_start_response(status, headers, exc_info=None):
             # Only set the cache control for succesful requests (200, 206).
             if status.startswith('20'):
@@ -60,10 +76,4 @@
                     headers, max_age=10*CACHE_CONTROL.ONE_YEAR)
                 EXPIRES.update(headers, delta=expires)
             return start_response(status, headers, exc_info)
-
-        # Reconstruct information for the directory_app to work with.
-        environ['PATH_INFO'] = '/' + '/'.join(new_path)
-        return directory_app(environ, cache_header_start_response)
-
-def make_publisher(app, global_conf):
-    return Publisher(app)
+"""



More information about the checkins mailing list