[Checkins] SVN: hurry.resource/branches/janjaapdriessen-resource-publisher/src/hurry/resource/ make the resource publisher a filter not an app. change order of library_name and hash. only publish when the has signature can be found

Jan-Wijbrand Kolman janwijbrand at gmail.com
Fri Nov 19 07:44:34 EST 2010


Log message for revision 118489:
  make the resource publisher a filter not an app. change order of library_name and hash. only publish when the has signature can be found

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-19 12:16:15 UTC (rev 118488)
+++ hurry.resource/branches/janjaapdriessen-resource-publisher/src/hurry/resource/README.txt	2010-11-19 12:44:34 UTC (rev 118489)
@@ -753,9 +753,9 @@
 for instance)::
 
   >>> print needed.render()
-  <link rel="stylesheet" type="text/css" href="http://localhost/static/foo/hash:.../b.css" />
-  <script type="text/javascript" src="http://localhost/static/foo/hash:.../a.js"></script>
-  <script type="text/javascript" src="http://localhost/static/foo/hash:.../c.js"></script>
+  <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>
 
 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/foo/hash:.../b.css" />
-  <script type="text/javascript" src="http://localhost/static/foo/hash:.../a.js"></script>
-  <script type="text/javascript" src="http://localhost/static/foo/hash:.../c.js"></script>
+  <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>
 
 Hashing resources
 =================
@@ -786,7 +786,7 @@
 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/:hash:12345/myresource instead of /foo/myresource.
 
 The default hashing behavior can be changed by setting the 'hashing' variable
 in the hurry.resource module through the `configure_hashing` function::
@@ -800,9 +800,9 @@
 
   >>> hurry.resource.configure_hashing(True)
   >>> print resource.render()
-  <link rel="stylesheet" type="text/css" href="http://localhost/static/foo/hash:.../b.css" />
-  <script type="text/javascript" src="http://localhost/static/foo/hash:.../a.js"></script>
-  <script type="text/javascript" src="http://localhost/static/foo/hash:.../c.js"></script>
+  <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>
 
 More about the devmode in a minute::
 
@@ -881,9 +881,9 @@
 
   >>> print needed.render_into_html(html)
   <html><head>
-      <link rel="stylesheet" type="text/css" href="http://localhost/static/foo/hash:.../b.css" />
-  <script type="text/javascript" src="http://localhost/static/foo/hash:.../a.js"></script>
-  <script type="text/javascript" src="http://localhost/static/foo/hash:.../c.js"></script>
+      <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>
   something more</head></html>
 
 The top-level convenience function does this for the currently needed
@@ -891,9 +891,9 @@
 
   >>> print resource.render_into_html(html)
   <html><head>
-      <link rel="stylesheet" type="text/css" href="http://localhost/static/foo/hash:...b.css" />
-  <script type="text/javascript" src="http://localhost/static/foo/hash:.../a.js"></script>
-  <script type="text/javascript" src="http://localhost/static/foo/hash:.../c.js"></script>
+      <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>
   something more</head></html>
 
 See below for a way to insert into HTML when bottom fragments are
@@ -914,9 +914,9 @@
 
   >>> top, bottom = needed.render_topbottom()
   >>> print top
-  <link rel="stylesheet" type="text/css" href="http://localhost/static/foo/hash:.../b.css" />
-  <script type="text/javascript" src="http://localhost/static/foo/hash:.../a.js"></script>
-  <script type="text/javascript" src="http://localhost/static/foo/hash:.../c.js"></script>
+  <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>
   >>> print bottom
   <BLANKLINE>
 
@@ -931,9 +931,9 @@
 
   >>> top, bottom = needed.render_topbottom()
   >>> print top
-  <link rel="stylesheet" type="text/css" href="http://localhost/static/foo/hash:.../b.css" />
-  <script type="text/javascript" src="http://localhost/static/foo/hash:.../a.js"></script>
-  <script type="text/javascript" src="http://localhost/static/foo/hash:.../c.js"></script>
+  <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>
   >>> print bottom
   <BLANKLINE>
 
@@ -943,10 +943,10 @@
   >>> needed.bottom(force=True)
   >>> top, bottom = needed.render_topbottom()
   >>> print top
-  <link rel="stylesheet" type="text/css" href="http://localhost/static/foo/hash:.../b.css" />
+  <link rel="stylesheet" type="text/css" href="http://localhost/static/:hash:.../foo/b.css" />
   >>> print bottom
-  <script type="text/javascript" src="http://localhost/static/foo/hash:.../a.js"></script>
-  <script type="text/javascript" src="http://localhost/static/foo/hash:.../c.js"></script>
+  <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>
 
 Let's now introduce a javascript resource that says it is safe to be
 included on the bottom::
@@ -963,10 +963,10 @@
 
   >>> top, bottom = needed.render_topbottom()
   >>> print top
-  <link rel="stylesheet" type="text/css" href="http://localhost/static/foo/hash:.../b.css" />
-  <script type="text/javascript" src="http://localhost/static/foo/hash:.../a.js"></script>
-  <script type="text/javascript" src="http://localhost/static/foo/hash:.../c.js"></script>
-  <script type="text/javascript" src="http://localhost/static/foo/hash:.../y2.js"></script>
+  <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>
   >>> print bottom
   <BLANKLINE>
 
@@ -978,22 +978,22 @@
 
   >>> top, bottom = needed.render_topbottom()
   >>> print top
-  <link rel="stylesheet" type="text/css" href="http://localhost/static/foo/hash:.../b.css" />
-  <script type="text/javascript" src="http://localhost/static/foo/hash:.../a.js"></script>
-  <script type="text/javascript" src="http://localhost/static/foo/hash:.../c.js"></script>
+  <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>
   >>> print bottom
-  <script type="text/javascript" src="http://localhost/static/foo/hash:.../y2.js"></script>
+  <script type="text/javascript" src="http://localhost/static/: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/foo/hash:.../b.css" />
-  <script type="text/javascript" src="http://localhost/static/foo/hash:.../a.js"></script>
-  <script type="text/javascript" src="http://localhost/static/foo/hash:.../c.js"></script>
+  <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>
   >>> print bottom
-  <script type="text/javascript" src="http://localhost/static/foo/hash:.../y2.js"></script>
+  <script type="text/javascript" src="http://localhost/static/: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
@@ -1002,11 +1002,11 @@
   >>> needed.bottom(force=True)
   >>> top, bottom = needed.render_topbottom()
   >>> print top
-  <link rel="stylesheet" type="text/css" href="http://localhost/static/foo/hash:.../b.css" />
+  <link rel="stylesheet" type="text/css" href="http://localhost/static/:hash:.../foo/b.css" />
   >>> print bottom
-  <script type="text/javascript" src="http://localhost/static/foo/hash:.../a.js"></script>
-  <script type="text/javascript" src="http://localhost/static/foo/hash:.../c.js"></script>
-  <script type="text/javascript" src="http://localhost/static/foo/hash:.../y2.js"></script>
+  <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>
 
 Note that if ``bottom`` is enabled, it makes no sense to have a
 resource inclusion ``b`` that depends on a resource inclusion ``a``
@@ -1037,20 +1037,20 @@
 
   >>> print needed.render_topbottom_into_html(html)
   <html><head>
-      <link rel="stylesheet" type="text/css" href="http://localhost/static/foo/hash:.../b.css" />
-  rest of head</head><body>rest of body<script type="text/javascript" src="http://localhost/static/foo/hash:.../a.js"></script>
-  <script type="text/javascript" src="http://localhost/static/foo/hash:.../c.js"></script>
-  <script type="text/javascript" src="http://localhost/static/foo/hash:.../y2.js"></script></body></html>
+      <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>
 
 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/foo/hash:.../b.css" />
-  rest of head</head><body>rest of body<script type="text/javascript" src="http://localhost/static/foo/hash:.../a.js"></script>
-  <script type="text/javascript" src="http://localhost/static/foo/hash:.../c.js"></script>
-  <script type="text/javascript" src="http://localhost/static/foo/hash:.../y2.js"></script></body></html>
+      <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>
 
 Using WSGI middleware to insert into HTML
 =========================================
@@ -1085,9 +1085,9 @@
 
   >>> print res.body
   <html><head>
-      <link rel="stylesheet" type="text/css" href="http://localhost/static/foo/hash:.../b.css" />
-  <script type="text/javascript" src="http://localhost/static/foo/hash:.../a.js"></script>
-  <script type="text/javascript" src="http://localhost/static/foo/hash:.../c.js"></script>
+      <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>
   </head><body</body></html>
 
 When we set the response Content-Type to non-HTML, the middleware
@@ -1121,7 +1121,7 @@
   >>> c.base_url = 'http://localhost/static'
   >>> top, bottom = c.render_topbottom()
   >>> print top
-  <script type="text/javascript" src="http://localhost/static/foo/hash:.../l1.js"></script>
+  <script type="text/javascript" src="http://localhost/static/:hash:.../foo/l1.js"></script>
   >>> print bottom
   <BLANKLINE>
 
@@ -1137,7 +1137,7 @@
   >>> print top
   <BLANKLINE>
   >>> print bottom
-  <script type="text/javascript" src="http://localhost/static/foo/hash:.../l1.js"></script>
+  <script type="text/javascript" src="http://localhost/static/:hash:.../foo/l1.js"></script>
 
 Generating resource code
 ========================
@@ -1257,7 +1257,7 @@
   >>> inclusion_renderers['.unknown'] = render_unknown
 
   >>> render_inclusions([a6], 'http://localhost/static/')
-  '<link rel="unknown" href="http://localhost/static/foo/hash:.../nothing.unknown" />'
+  '<link rel="unknown" href="http://localhost/static/:hash:.../foo/nothing.unknown" />'
 
 
 Resource publisher
@@ -1268,7 +1268,11 @@
 
   >>> from hurry.resource.publisher import Publisher
   >>> from paste.fixture import TestApp
-  >>> app = TestApp(Publisher())
+  >>> from paste.httpexceptions import HTTPNotFound
+  >>> class NoFindNoResource(object):
+  ... 	    def __call__(self, environ, start_response):
+  ...	    	return HTTPNotFound()(environ, start_response)
+  >>> app = TestApp(Publisher(NoFindNoResource()))
 
 We don't do anything fancy if the resource can not be found, but raise 404.
 
@@ -1279,19 +1283,19 @@
 The resources are handled by paste.fileapp.DirectoryApp, which sets the
 ETag header, among other things::
 
-  >>> res = app.get('/foo/style.css')
-  >>> print res.body
+  <<< res = app.get('/foo/style.css')
+  <<< print res.body
   body {
     color: #f00;
   }
-  >>> headers = dict(res.headers)
-  >>> 'ETag' in headers
+  <<< 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.
 
-  >>> res = app.get('/foo/hash:12345/style.css')
+  >>> res = app.get('/:hash:12345/foo/style.css')
   >>> headers = dict(res.headers)
   >>> 'Expires' in headers
   True
@@ -1300,7 +1304,7 @@
 
 We don't set cache-control headers on non-successful responses::
 
-  >>> res = app.get('/foo/hash:12345/notfound.css', expect_errors=True)
+  >>> res = app.get('/:hash:12345/foo/notfound.css', expect_errors=True)
   >>> headers = dict(res.headers)
   >>> 'Expires' in headers
   False

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-19 12:16:15 UTC (rev 118488)
+++ hurry.resource/branches/janjaapdriessen-resource-publisher/src/hurry/resource/__init__.py	2010-11-19 12:44:34 UTC (rev 118489)
@@ -21,6 +21,8 @@
     global hashing
     hashing = enable
 
+hash_signature = 'hash'
+
 devmode = False
 
 def configure_devmode(enable=True):

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-19 12:16:15 UTC (rev 118488)
+++ hurry.resource/branches/janjaapdriessen-resource-publisher/src/hurry/resource/core.py	2010-11-19 12:44:34 UTC (rev 118489)
@@ -28,8 +28,8 @@
         self.path = os.path.join(caller_dir(), rootpath)
 
     def hash(self):
-        # Only compute the checksum if (1) it has not been computed before OR
-        # (2) we are in development mode.
+        # Only compute the checksum if (1) it has not been computed
+        # before or (2) we are in development mode.
         if self._hash is None or hurry.resource.devmode:
             self._hash = hurry.resource.hash.checksum(self.path)
         return self._hash
@@ -434,21 +434,22 @@
     hash_cache = {}
     if base_url and not base_url.endswith('/'):
         base_url += '/'
+        
+    signature = ''
     for inclusion in inclusions:
         library = inclusion.library
-        library_url = base_url + inclusion.library.name + '/'
         if hurry.resource.hashing:
-             # For every request, compute the hash of each library only once.
-             # XXX This is a suboptimal optimization that we would like to factor
-             # out.
+             # For every request, compute the hash of each library
+             # only once.  XXX This is a suboptimal optimization that
+             # we would like to factor out.
              hash = hash_cache.get(library.name)
              if hash is None:
                  hash = library.hash()
                  hash_cache[library.name] = hash
-             library_url += 'hash:%s/' % hash
-
-        result.append(render_inclusion(inclusion,
-                                       library_url + inclusion.relpath))
+             signature = ':%s:%s/' % (hurry.resource.hash_signature, hash)
+        library_url = base_url + signature + inclusion.library.name + '/'
+        result.append(render_inclusion(
+            inclusion, library_url + inclusion.relpath))
     return '\n'.join(result)
 
 def render_inclusion(inclusion, url):

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-19 12:16:15 UTC (rev 118488)
+++ hurry.resource/branches/janjaapdriessen-resource-publisher/src/hurry/resource/publisher.py	2010-11-19 12:44:34 UTC (rev 118489)
@@ -1,3 +1,4 @@
+import webob
 from paste.request import path_info_pop, path_info_split
 from paste.fileapp import DirectoryApp, CACHE_CONTROL, EXPIRES
 from paste.httpexceptions import HTTPNotFound
@@ -15,17 +16,34 @@
 
 
 class Publisher(object):
-    def __init__(self):
+    def __init__(self, app, **local_conf):
+        self._wrapped_app = app
         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):
-        # When configured through Paste#urlmap, the WSGI environ['PATH_INFO']
-        # does not contain the mapping URL segment any more.
+        path = environ['PATH_INFO']
+        if hurry.resource.hash_signature not in path:
+            # There's no hash signature found in the path, so we
+            # cannot publish it from here. Leave the response to the
+            # wrapped app.
+            request = webob.Request(environ)
+            response = request.get_response(self._wrapped_app)
+            return response(environ, start_response)
 
-        library_name = path_info_pop(environ)
+        library_name = ''
+        next_ = path_info_pop(environ)
+        while next_:
+            if next_.startswith(':%s:' % hurry.resource.hash_signature):
+                # Skip over hash signature segment. The library name
+                # will be that of the next step.
+                library_name = path_info_pop(environ)
+                break
+            next_ = path_info_pop(environ)
+            print 'STEPPIE', library_name, path, environ['PATH_INFO']
+
         try:
             directory_app = self.directory_apps[library_name]
         except KeyError:
@@ -39,16 +57,8 @@
                 EXPIRES.update(headers, delta=expires)
             return start_response(status, headers, exc_info)
 
-        response = start_response
-
-        next_segment = path_info_split(environ['PATH_INFO'])[0]
-        if next_segment is not None and next_segment.startswith('hash:'):
-            # Our hashed urls start with 'hash:'. Skip these URL segments.
-            path_info_pop(environ)
-            response = cache_header_start_response
-
+        response = cache_header_start_response
         return directory_app(environ, response)
 
-
-def make_publisher(global_conf):
-    return Publisher()
+def make_publisher(app, global_conf, **local_conf):
+    return Publisher(app, **local_conf)



More information about the checkins mailing list