[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