# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: esteve@fluidinfo.com-20090330195126-0acrlpz52tgv04e6
# target_branch: ../trunk/
# testament_sha1: 7f04c737b5b3abdcc69717812cc66b0d10a62ec9
# timestamp: 2009-03-31 16:52:17 +0200
# base_revision_id: svn-v4:bbbe8e31-12d6-0310-92fd-\
# ac37d47ddeeb:trunk:26540
#
# Begin patch
=== modified file 'twisted/web/server.py'
--- twisted/web/server.py 2009-01-28 21:46:48 +0000
+++ twisted/web/server.py 2009-03-30 15:45:31 +0000
@@ -127,76 +127,86 @@
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)
+ def _cbRender(body):
+ if body == NOT_DONE_YET:
+ warnings.warn(
+ "Returning NOT_DONE_YET is deprecated, return a Deferred instead.",
+ DeprecationWarning, stacklevel=2)
+ return
+ if type(body) is not types.StringType:
+ body = resource.ErrorPage(
+ http.INTERNAL_SERVER_ERROR,
+ "Request did not return a string",
+ "Request: " + html.PRE(reflect.safe_repr(self)) + "
" +
+ "Resource: " + html.PRE(reflect.safe_repr(resrc)) + "
" +
+ "Value: " + html.PRE(reflect.safe_repr(body))).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:
+ if self.method == "HEAD":
+ if len(body) > 0:
+ # This is a Bad Thing (RFC 2616, 9.4)
+ log.msg("Warning: HEAD request %s for resource %s is"
+ " returning a message body."
+ " I think I'll eat it."
+ % (self, resrc))
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)s here.''' % {
- 'URI': self.uri,
- 'method': self.method,
- 'plural': ((len(allowedMethods) > 1) and 's') or '',
- 'allowed': string.join(allowedMethods, ', ')
- })
- epage = resource.ErrorPage(http.NOT_ALLOWED,
- "Method Not Allowed", s)
- body = epage.render(self)
else:
- epage = resource.ErrorPage(http.NOT_IMPLEMENTED, "Huh?",
- "I don't know how to treat a"
- " %s request." % (self.method,))
- body = epage.render(self)
- # end except UnsupportedMethod
-
- if body == NOT_DONE_YET:
- return
- if type(body) is not types.StringType:
- body = resource.ErrorPage(
- http.INTERNAL_SERVER_ERROR,
- "Request did not return a string",
- "Request: " + html.PRE(reflect.safe_repr(self)) + "
" +
- "Resource: " + html.PRE(reflect.safe_repr(resrc)) + "
" +
- "Value: " + html.PRE(reflect.safe_repr(body))).render(self)
-
- if self.method == "HEAD":
- if len(body) > 0:
- # This is a Bad Thing (RFC 2616, 9.4)
- log.msg("Warning: HEAD request %s for resource %s is"
- " returning a message body."
- " I think I'll eat it."
- % (self, resrc))
self.setHeader('content-length', str(len(body)))
- self.write('')
- else:
- self.setHeader('content-length', str(len(body)))
- self.write(body)
- self.finish()
+ self.write(body)
+ self.finish()
+
+ def _ebRender(fail):
+ r = fail.trap(UnsupportedMethod)
+ if r == UnsupportedMethod:
+ allowedMethods = fail.value.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)s here.''' % {
+ 'URI': self.uri,
+ 'method': self.method,
+ 'plural': ((len(allowedMethods) > 1) and 's') or '',
+ 'allowed': string.join(allowedMethods, ', ')
+ })
+ epage = resource.ErrorPage(http.NOT_ALLOWED,
+ "Method Not Allowed", s)
+ body = epage.render(self)
+ else:
+ epage = resource.ErrorPage(http.NOT_IMPLEMENTED, "Huh?",
+ "I don't know how to treat a"
+ " %s request." % (self.method,))
+ body = epage.render(self)
+ # end except UnsupportedMethod
+ return _cbRender(body)
+
+ d = defer.maybeDeferred(resrc.render, self)
+ d.addCallbacks(_cbRender, _ebRender)
+ return d
def processingFailed(self, reason):
log.err(reason)
=== modified file 'twisted/web/test/test_web.py'
--- twisted/web/test/test_web.py 2009-01-28 21:46:48 +0000
+++ twisted/web/test/test_web.py 2009-03-30 19:51:26 +0000
@@ -181,6 +181,15 @@
else:
return "correct"
+class SimpleDeferredResource(resource.Resource):
+ def render(self, request):
+ d = defer.Deferred()
+ if http.CACHED in (request.setLastModified(10),
+ request.setETag('MatchingTag')):
+ reactor.callLater(0, d.callback, '')
+ else:
+ reactor.callLater(0, d.callback, "correct")
+ return d
class DummyChannel:
class TCP:
@@ -231,6 +240,18 @@
site.getResourceFor(DummyRequest([''])),
sres2, "Got the wrong resource.")
+ def test_simplestSiteDeferred(self):
+ """
+ L{Site.getResourceFor} returns the C{""} child of the root resource it
+ is constructed with when processing a request for I{/}.
+ """
+ sres1 = SimpleDeferredResource()
+ sres2 = SimpleDeferredResource()
+ sres1.putChild("",sres2)
+ site = server.Site(sres1)
+ self.assertIdentical(
+ site.getResourceFor(DummyRequest([''])),
+ sres2, "Got the wrong resource.")
class SessionTest(unittest.TestCase):
# Begin bundle
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
ZQUdKgXe9budIUwfxdyRThQkEyJEQcA=