| 130 | | try: |
| 131 | | body = resrc.render(self) |
| 132 | | except UnsupportedMethod, e: |
| 133 | | allowedMethods = e.allowedMethods |
| 134 | | if (self.method == "HEAD") and ("GET" in allowedMethods): |
| 135 | | # We must support HEAD (RFC 2616, 5.1.1). If the |
| 136 | | # resource doesn't, fake it by giving the resource |
| 137 | | # a 'GET' request and then return only the headers, |
| 138 | | # not the body. |
| 139 | | log.msg("Using GET to fake a HEAD request for %s" % |
| 140 | | (resrc,)) |
| 141 | | self.method = "GET" |
| 142 | | body = resrc.render(self) |
| | 130 | def _cbRender(body): |
| | 131 | if body == NOT_DONE_YET: |
| | 132 | warnings.warn( |
| | 133 | "Returning NOT_DONE_YET is deprecated, return a Deferred instead.", |
| | 134 | DeprecationWarning, stacklevel=2) |
| | 135 | return |
| | 136 | if type(body) is not types.StringType: |
| | 137 | body = resource.ErrorPage( |
| | 138 | http.INTERNAL_SERVER_ERROR, |
| | 139 | "Request did not return a string", |
| | 140 | "Request: " + html.PRE(reflect.safe_repr(self)) + "<br />" + |
| | 141 | "Resource: " + html.PRE(reflect.safe_repr(resrc)) + "<br />" + |
| | 142 | "Value: " + html.PRE(reflect.safe_repr(body))).render(self) |
| 152 | | self.finish() |
| 153 | | return |
| 154 | | |
| 155 | | if self.method in (supportedMethods): |
| 156 | | # We MUST include an Allow header |
| 157 | | # (RFC 2616, 10.4.6 and 14.7) |
| 158 | | self.setHeader('Allow', allowedMethods) |
| 159 | | s = ('''Your browser approached me (at %(URI)s) with''' |
| 160 | | ''' the method "%(method)s". I only allow''' |
| 161 | | ''' the method%(plural)s %(allowed)s here.''' % { |
| 162 | | 'URI': self.uri, |
| 163 | | 'method': self.method, |
| 164 | | 'plural': ((len(allowedMethods) > 1) and 's') or '', |
| 165 | | 'allowed': string.join(allowedMethods, ', ') |
| 166 | | }) |
| 167 | | epage = resource.ErrorPage(http.NOT_ALLOWED, |
| 168 | | "Method Not Allowed", s) |
| 169 | | body = epage.render(self) |
| 171 | | epage = resource.ErrorPage(http.NOT_IMPLEMENTED, "Huh?", |
| 172 | | "I don't know how to treat a" |
| 173 | | " %s request." % (self.method,)) |
| 174 | | body = epage.render(self) |
| 175 | | # end except UnsupportedMethod |
| 176 | | |
| 177 | | if body == NOT_DONE_YET: |
| 178 | | return |
| 179 | | if type(body) is not types.StringType: |
| 180 | | body = resource.ErrorPage( |
| 181 | | http.INTERNAL_SERVER_ERROR, |
| 182 | | "Request did not return a string", |
| 183 | | "Request: " + html.PRE(reflect.safe_repr(self)) + "<br />" + |
| 184 | | "Resource: " + html.PRE(reflect.safe_repr(resrc)) + "<br />" + |
| 185 | | "Value: " + html.PRE(reflect.safe_repr(body))).render(self) |
| 186 | | |
| 187 | | if self.method == "HEAD": |
| 188 | | if len(body) > 0: |
| 189 | | # This is a Bad Thing (RFC 2616, 9.4) |
| 190 | | log.msg("Warning: HEAD request %s for resource %s is" |
| 191 | | " returning a message body." |
| 192 | | " I think I'll eat it." |
| 193 | | % (self, resrc)) |
| 195 | | self.write('') |
| 196 | | else: |
| 197 | | self.setHeader('content-length', str(len(body))) |
| 198 | | self.write(body) |
| 199 | | self.finish() |
| | 155 | self.write(body) |
| | 156 | self.finish() |
| | 157 | |
| | 158 | def _ebRender(fail): |
| | 159 | r = fail.trap(UnsupportedMethod) |
| | 160 | if r == UnsupportedMethod: |
| | 161 | allowedMethods = fail.value.allowedMethods |
| | 162 | |
| | 163 | if (self.method == "HEAD") and ("GET" in allowedMethods): |
| | 164 | # We must support HEAD (RFC 2616, 5.1.1). If the |
| | 165 | # resource doesn't, fake it by giving the resource |
| | 166 | # a 'GET' request and then return only the headers, |
| | 167 | # not the body. |
| | 168 | log.msg("Using GET to fake a HEAD request for %s" % |
| | 169 | (resrc,)) |
| | 170 | self.method = "GET" |
| | 171 | body = resrc.render(self) |
| | 172 | |
| | 173 | if body is NOT_DONE_YET: |
| | 174 | log.msg("Tried to fake a HEAD request for %s, but " |
| | 175 | "it got away from me." % resrc) |
| | 176 | # Oh well, I guess we won't include the content length. |
| | 177 | else: |
| | 178 | self.setHeader('content-length', str(len(body))) |
| | 179 | |
| | 180 | self.write('') |
| | 181 | self.finish() |
| | 182 | return |
| | 183 | |
| | 184 | if self.method in (supportedMethods): |
| | 185 | # We MUST include an Allow header |
| | 186 | # (RFC 2616, 10.4.6 and 14.7) |
| | 187 | self.setHeader('Allow', allowedMethods) |
| | 188 | s = ('''Your browser approached me (at %(URI)s) with''' |
| | 189 | ''' the method "%(method)s". I only allow''' |
| | 190 | ''' the method%(plural)s %(allowed)s here.''' % { |
| | 191 | 'URI': self.uri, |
| | 192 | 'method': self.method, |
| | 193 | 'plural': ((len(allowedMethods) > 1) and 's') or '', |
| | 194 | 'allowed': string.join(allowedMethods, ', ') |
| | 195 | }) |
| | 196 | epage = resource.ErrorPage(http.NOT_ALLOWED, |
| | 197 | "Method Not Allowed", s) |
| | 198 | body = epage.render(self) |
| | 199 | else: |
| | 200 | epage = resource.ErrorPage(http.NOT_IMPLEMENTED, "Huh?", |
| | 201 | "I don't know how to treat a" |
| | 202 | " %s request." % (self.method,)) |
| | 203 | body = epage.render(self) |
| | 204 | # end except UnsupportedMethod |
| | 205 | return _cbRender(body) |
| | 206 | |
| | 207 | d = defer.maybeDeferred(resrc.render, self) |
| | 208 | d.addCallbacks(_cbRender, _ebRender) |
| | 209 | return d |