[Twisted-Python] Patch to allow deferreds to be returned from resource.render

James Y. Knight foom at fuhm.net
Sun Sep 14 06:22:27 EDT 2003


Ooh lets try sending this mail one more time. Apparently the combined 
suckage of three different programs made my last mail not get through:
1) Apple Mail sucks and doesn't quote the "Full Name" automatically, so 
I end up with a non-RFC-conforming From: with a "." outside of quotes 
or the email address.
2) Exim sucks and doesn't fix it (OTOH, Sendmail does fix it, which is 
why i've never seen this problem before!)
3) Mailman sucks as well, and gets completely confused by this slightly 
non-conformant address format, and thinks my email address is 
"jamesy.knight".

Anyways, on to the original message:
===

This patch lets you return a deferred from resource.render (the obvious 
thing to do) and have it work. As opposed to the current method where 
you need to return NOT_DONE_YET and restructure all your code to call 
request.write(...). That should still work too, though. I'd stick this 
on the bug tracker but I forgot my password. (anyone able to reset for 
me? :)

James

--- server.py~  Mon Jul 21 00:09:52 2003
+++ server.py   Tue Sep  9 15:02:09 2003
@@ -160,56 +160,8 @@
          except:
              self.processingFailed(failure.Failure())

-
-    def render(self, resrc):
-        try:
-            body = resrc.render(self)
-        except UnsupportedMethod, e:
-            allowedMethods = e.allowedMethods
-            if (self.method == "HEAD") and ("GET" in allowedMethods):
-                # We must support HEAD (RFC 2616, 5.1.1).  If the
-                # resource doesn't, fake it by giving the resource
-                # a 'GET' request and then return only the headers,
-                # not the body.
-                log.msg("Using GET to fake a HEAD request for %s" %
-                        (resrc,))
-                self.method = "GET"
-                body = resrc.render(self)
-
-                if body is NOT_DONE_YET:
-                    log.msg("Tried to fake a HEAD request for %s, but "
-                            "it got away from me." % resrc)
-                    # Oh well, I guess we won't include the content 
length.
-                else:
-                    self.setHeader('content-length', str(len(body)))
-
-                self.write('')
-                self.finish()
-                return
-
-            if self.method in (supportedMethods):
-                # We MUST include an Allow header
-                # (RFC 2616, 10.4.6 and 14.7)
-                self.setHeader('Allow', allowedMethods)
-                s = ('''Your browser approached me (at %(URI)s) with'''
-                     ''' the method "%(method)s".  I only allow'''
-                     ''' the method%(plural)s %(allowed) here.''' % {
-                    'URI': self.uri,
-                    'method': self.method,
-                    'plural': ((len(allowedMethods) > 1) and 's') or 
'',
-                    'allowed': string.join(allowedMethods, ', ')
-                    })
-                epage = error.ErrorPage(http.NOT_ALLOWED,
-                                        "Method Not Allowed", s)
-                body = epage.render(self)
-            else:
-                epage = error.ErrorPage(http.NOT_IMPLEMENTED, "Huh?",
-                                        """I don't know how to treat 
a"""
-                                        """ %s request."""
-                                        % (self.method))
-                body = epage.render(self)
-        # end except UnsupportedMethod
-
+    def _cbRender(self, body, resrc):
+
          if body == NOT_DONE_YET:
              return
          if type(body) is not types.StringType:
@@ -232,6 +184,58 @@
              self.setHeader('content-length', str(len(body)))
              self.write(body)
          self.finish()
+
+    def _ebRender(self, failure, resrc):
+        failure.trap(UnsupportedMethod)
+        e = failure.value
+        allowedMethods = e.allowedMethods
+        if (self.method == "HEAD") and ("GET" in allowedMethods):
+            # We must support HEAD (RFC 2616, 5.1.1).  If the
+            # resource doesn't, fake it by giving the resource
+            # a 'GET' request and then return only the headers,
+            # not the body.
+            log.msg("Using GET to fake a HEAD request for %s" %
+                    (resrc,))
+            self.method = "GET"
+            body = resrc.render(self)
+
+            if body is NOT_DONE_YET:
+                log.msg("Tried to fake a HEAD request for %s, but "
+                        "it got away from me." % resrc)
+                # Oh well, I guess we won't include the content length.
+            else:
+                self.setHeader('content-length', str(len(body)))
+
+            self.write('')
+            self.finish()
+            return
+
+        if self.method in (supportedMethods):
+            # We MUST include an Allow header
+            # (RFC 2616, 10.4.6 and 14.7)
+            self.setHeader('Allow', allowedMethods)
+            s = ('''Your browser approached me (at %(URI)s) with'''
+                 ''' the method "%(method)s".  I only allow'''
+                 ''' the method%(plural)s %(allowed) here.''' % {
+                'URI': self.uri,
+                'method': self.method,
+                'plural': ((len(allowedMethods) > 1) and 's') or '',
+                'allowed': string.join(allowedMethods, ', ')
+                })
+            epage = error.ErrorPage(http.NOT_ALLOWED,
+                                    "Method Not Allowed", s)
+            body = epage.render(self)
+        else:
+            epage = error.ErrorPage(http.NOT_IMPLEMENTED, "Huh?",
+                                    """I don't know how to treat a"""
+                                    """ %s request."""
+                                    % (self.method))
+            body = epage.render(self)
+
+    def render(self, resrc):
+        defer.maybeDeferred(resrc.render, 
self).addErrback(self._ebRender, resrc).addCallback(self._cbRender, 
resrc).addErrback(self.processingFailed)
+
+

      def processingFailed(self, reason):
          log.err(reason)





More information about the Twisted-Python mailing list