Ticket #253: render-deferred.patch

File render-deferred.patch, 5.0 KB (added by jknight, 13 years ago)
  • server.py

    old new  
    160160        except:
    161161            self.processingFailed(failure.Failure())
    162162
    163 
    164     def render(self, resrc):
    165         try:
    166             body = resrc.render(self)
    167         except UnsupportedMethod, e:
    168             allowedMethods = e.allowedMethods
    169             if (self.method == "HEAD") and ("GET" in allowedMethods):
    170                 # We must support HEAD (RFC 2616, 5.1.1).  If the
    171                 # resource doesn't, fake it by giving the resource
    172                 # a 'GET' request and then return only the headers,
    173                 # not the body.
    174                 log.msg("Using GET to fake a HEAD request for %s" %
    175                         (resrc,))
    176                 self.method = "GET"
    177                 body = resrc.render(self)
    178 
    179                 if body is NOT_DONE_YET:
    180                     log.msg("Tried to fake a HEAD request for %s, but "
    181                             "it got away from me." % resrc)
    182                     # Oh well, I guess we won't include the content length.
    183                 else:
    184                     self.setHeader('content-length', str(len(body)))
    185 
    186                 self.write('')
    187                 self.finish()
    188                 return
    189 
    190             if self.method in (supportedMethods):
    191                 # We MUST include an Allow header
    192                 # (RFC 2616, 10.4.6 and 14.7)
    193                 self.setHeader('Allow', allowedMethods)
    194                 s = ('''Your browser approached me (at %(URI)s) with'''
    195                      ''' the method "%(method)s".  I only allow'''
    196                      ''' the method%(plural)s %(allowed) here.''' % {
    197                     'URI': self.uri,
    198                     'method': self.method,
    199                     'plural': ((len(allowedMethods) > 1) and 's') or '',
    200                     'allowed': string.join(allowedMethods, ', ')
    201                     })
    202                 epage = error.ErrorPage(http.NOT_ALLOWED,
    203                                         "Method Not Allowed", s)
    204                 body = epage.render(self)
    205             else:
    206                 epage = error.ErrorPage(http.NOT_IMPLEMENTED, "Huh?",
    207                                         """I don't know how to treat a"""
    208                                         """ %s request."""
    209                                         % (self.method))
    210                 body = epage.render(self)
    211         # end except UnsupportedMethod
    212 
     163    def _cbRender(self, body, resrc):
     164
    213165        if body == NOT_DONE_YET:
    214166            return
    215167        if type(body) is not types.StringType:
     
    232184            self.setHeader('content-length', str(len(body)))
    233185            self.write(body)
    234186        self.finish()
     187
     188    def _ebRender(self, failure, resrc):
     189        failure.trap(UnsupportedMethod)
     190        e = failure.value
     191        allowedMethods = e.allowedMethods
     192        if (self.method == "HEAD") and ("GET" in allowedMethods):
     193            # We must support HEAD (RFC 2616, 5.1.1).  If the
     194            # resource doesn't, fake it by giving the resource
     195            # a 'GET' request and then return only the headers,
     196            # not the body.
     197            log.msg("Using GET to fake a HEAD request for %s" %
     198                    (resrc,))
     199            self.method = "GET"
     200            body = resrc.render(self)
     201
     202            if body is NOT_DONE_YET:
     203                log.msg("Tried to fake a HEAD request for %s, but "
     204                        "it got away from me." % resrc)
     205                # Oh well, I guess we won't include the content length.
     206            else:
     207                self.setHeader('content-length', str(len(body)))
     208
     209            self.write('')
     210            self.finish()
     211            return
     212
     213        if self.method in (supportedMethods):
     214            # We MUST include an Allow header
     215            # (RFC 2616, 10.4.6 and 14.7)
     216            self.setHeader('Allow', allowedMethods)
     217            s = ('''Your browser approached me (at %(URI)s) with'''
     218                 ''' the method "%(method)s".  I only allow'''
     219                 ''' the method%(plural)s %(allowed) here.''' % {
     220                'URI': self.uri,
     221                'method': self.method,
     222                'plural': ((len(allowedMethods) > 1) and 's') or '',
     223                'allowed': string.join(allowedMethods, ', ')
     224                })
     225            epage = error.ErrorPage(http.NOT_ALLOWED,
     226                                    "Method Not Allowed", s)
     227            body = epage.render(self)
     228        else:
     229            epage = error.ErrorPage(http.NOT_IMPLEMENTED, "Huh?",
     230                                    """I don't know how to treat a"""
     231                                    """ %s request."""
     232                                    % (self.method))
     233            body = epage.render(self)
     234
     235    def render(self, resrc):
     236        defer.maybeDeferred(resrc.render, self).addErrback(self._ebRender, resrc).addCallback(self._cbRender, resrc).addErrback(self.processingFailed)
     237
     238
    235239
    236240    def processingFailed(self, reason):
    237241        log.err(reason)