[Checkins] SVN: hurry.resource/trunk/ Add a WSGI middleware that will pull in resources.

Martijn Faassen faassen at startifact.com
Tue Jul 13 11:36:26 EDT 2010


Log message for revision 114697:
  Add a WSGI middleware that will pull in resources.
  

Changed:
  U   hurry.resource/trunk/CHANGES.txt
  U   hurry.resource/trunk/buildout.cfg
  U   hurry.resource/trunk/setup.py
  U   hurry.resource/trunk/src/hurry/resource/README.txt
  U   hurry.resource/trunk/src/hurry/resource/__init__.py
  A   hurry.resource/trunk/src/hurry/resource/wsgi.py

-=-
Modified: hurry.resource/trunk/CHANGES.txt
===================================================================
--- hurry.resource/trunk/CHANGES.txt	2010-07-13 11:15:40 UTC (rev 114696)
+++ hurry.resource/trunk/CHANGES.txt	2010-07-13 15:36:25 UTC (rev 114697)
@@ -1,9 +1,17 @@
 CHANGES
 *******
 
-0.4.2 (unreleased)
-==================
+0.5 (unreleased)
+================
 
+* WSGI support: ``hurry.resource.Middleware`` can be used to wrap WSGI
+  applications. If the application supplies a ``NeededInclusions``
+  object in ``environ`` with the key ``hurry.resource.needed``, the
+  middleware will pick up on this and insert the needed inclusions.
+  
+  The WebOb library is needed to make this work and depending on
+  ``hurry.resource [wsgi]`` will pull in the required dependency.
+
 * Fixed some typos in README.txt.
 
 0.4.1 (2009-12-16)

Modified: hurry.resource/trunk/buildout.cfg
===================================================================
--- hurry.resource/trunk/buildout.cfg	2010-07-13 11:15:40 UTC (rev 114696)
+++ hurry.resource/trunk/buildout.cfg	2010-07-13 15:36:25 UTC (rev 114697)
@@ -2,12 +2,13 @@
 develop = .
 parts = test releaser
 versions = versions
+unzip = true
 
 [versions]
 
 [test]
 recipe = zc.recipe.testrunner
-eggs = hurry.resource
+eggs = hurry.resource [test]
 defaults = ['--tests-pattern', '^f?tests$', '-v']
 
 [releaser]

Modified: hurry.resource/trunk/setup.py
===================================================================
--- hurry.resource/trunk/setup.py	2010-07-13 11:15:40 UTC (rev 114696)
+++ hurry.resource/trunk/setup.py	2010-07-13 15:36:25 UTC (rev 114697)
@@ -33,5 +33,7 @@
         'zope.interface',
         'zope.component',
         ],
+    extras_require = dict(test=['WebOb'],
+                          wsgi=['WebOb']),
     entry_points={},
     )

Modified: hurry.resource/trunk/src/hurry/resource/README.txt
===================================================================
--- hurry.resource/trunk/src/hurry/resource/README.txt	2010-07-13 11:15:40 UTC (rev 114696)
+++ hurry.resource/trunk/src/hurry/resource/README.txt	2010-07-13 15:36:25 UTC (rev 114697)
@@ -937,6 +937,58 @@
   <script type="text/javascript" src="http://localhost/static/foo/c.js"></script>
   <script type="text/javascript" src="http://localhost/static/foo/y2.js"></script></body></html>
 
+Using WSGI middleware to insert into HTML
+=========================================
+
+There is also a WSGI middleware available to insert the top (and bottom)
+into the HTML. We are using WebOb to create a response object that will
+serve as our WSGI application::
+
+We create a simple WSGI application. In our application we declare that
+we need a resource (``y1``) and put that in the WSGI ``environ`` under the
+key ``hurry.resource.needed``::
+ 
+  >>> def app(environ, start_response):
+  ...    start_response('200 OK', [])
+  ...    needed = environ['hurry.resource.needed'] = NeededInclusions()
+  ...    needed.need(y1)
+  ...    return ['<html><head></head><body</body></html>']
+
+We now wrap this in our middleware, so that the middleware is activated::
+
+  >>> from hurry.resource import Middleware
+  >>> wrapped_app = Middleware(app)
+
+Now we make a request (using webob for convenience)::
+
+  >>> import webob
+  >>> req = webob.Request.blank('/')
+  >>> res = req.get_response(wrapped_app) 
+
+We can now see that the resources are added to the HTML by the middleware::
+
+  >>> print res.body
+  <html><head>
+      <link rel="stylesheet" type="text/css" href="http://localhost/static/foo/b.css" />
+  <script type="text/javascript" src="http://localhost/static/foo/a.js"></script>
+  <script type="text/javascript" src="http://localhost/static/foo/c.js"></script>
+  </head><body</body></html>
+
+When we set the response Content-Type to non-HTML, the middleware
+won't be active even if we need things and the body appears to contain
+HTML::
+
+  >>> def app(environ, start_response):
+  ...    start_response('200 OK', [('Content-Type', 'text/plain')])
+  ...    needed = environ['hurry.resource.needed'] = NeededInclusions()
+  ...    needed.need(y1)
+  ...    return ['<html><head></head><body</body></html>']
+  >>> wrapped_app = Middleware(app)
+  >>> req = webob.Request.blank('/')
+  >>> res = req.get_response(wrapped_app)
+  >>> res.body
+  '<html><head></head><body</body></html>'
+
 bottom convenience
 ==================
 

Modified: hurry.resource/trunk/src/hurry/resource/__init__.py
===================================================================
--- hurry.resource/trunk/src/hurry/resource/__init__.py	2010-07-13 11:15:40 UTC (rev 114696)
+++ hurry.resource/trunk/src/hurry/resource/__init__.py	2010-07-13 15:36:25 UTC (rev 114697)
@@ -10,3 +10,4 @@
 from hurry.resource.core import (sort_inclusions_topological,
                                  sort_inclusions_by_extension,
                                  generate_code)
+from hurry.resource.wsgi import Middleware

Added: hurry.resource/trunk/src/hurry/resource/wsgi.py
===================================================================
--- hurry.resource/trunk/src/hurry/resource/wsgi.py	                        (rev 0)
+++ hurry.resource/trunk/src/hurry/resource/wsgi.py	2010-07-13 15:36:25 UTC (rev 114697)
@@ -0,0 +1,21 @@
+import webob
+
+# TODO: would be nice to make middleware smarter so it could work with
+# a streamed HTML body instead of serializing it out to body. That
+# would complicate the middleware signicantly, however. We would for
+# instance need to recalculate content_length ourselves.
+
+class Middleware(object):
+    def __init__(self, application):
+        self.application = application
+
+    def __call__(self, environ, start_response):
+        req = webob.Request(environ)
+        res = req.get_response(self.application)
+        if not res.content_type.lower() in ['text/html', 'text/xml']:
+            return res(environ, start_response)
+        needed = environ.get('hurry.resource.needed', None)
+        if needed is None:
+            return res(environ, start_response)
+        res.body = needed.render_topbottom_into_html(res.body)
+        return res(environ, start_response)



More information about the checkins mailing list