| 131 | | try: |
| 132 | | body = resrc.render(self) |
| 133 | | except UnsupportedMethod, e: |
| 134 | | allowedMethods = e.allowedMethods |
| 135 | | if (self.method == "HEAD") and ("GET" in allowedMethods): |
| 136 | | # We must support HEAD (RFC 2616, 5.1.1). If the |
| 137 | | # resource doesn't, fake it by giving the resource |
| 138 | | # a 'GET' request and then return only the headers, |
| 139 | | # not the body. |
| 140 | | log.msg("Using GET to fake a HEAD request for %s" % |
| 141 | | (resrc,)) |
| 142 | | self.method = "GET" |
| 143 | | body = resrc.render(self) |
| 144 | | |
| 145 | | if body is NOT_DONE_YET: |
| 146 | | log.msg("Tried to fake a HEAD request for %s, but " |
| 147 | | "it got away from me." % resrc) |
| 148 | | # Oh well, I guess we won't include the content length. |
| 149 | | else: |
| 150 | | self.setHeader('content-length', str(len(body))) |
| 151 | | |
| 152 | | self.write('') |
| 153 | | self.finish() |
| 154 | | return |
| 155 | | |
| 156 | | if self.method in (supportedMethods): |
| 157 | | # We MUST include an Allow header |
| 158 | | # (RFC 2616, 10.4.6 and 14.7) |
| 159 | | self.setHeader('Allow', allowedMethods) |
| 160 | | s = ('''Your browser approached me (at %(URI)s) with''' |
| 161 | | ''' the method "%(method)s". I only allow''' |
| 162 | | ''' the method%(plural)s %(allowed)s here.''' % { |
| 163 | | 'URI': self.uri, |
| 164 | | 'method': self.method, |
| 165 | | 'plural': ((len(allowedMethods) > 1) and 's') or '', |
| 166 | | 'allowed': string.join(allowedMethods, ', ') |
| 167 | | }) |
| 168 | | epage = resource.ErrorPage(http.NOT_ALLOWED, |
| 169 | | "Method Not Allowed", s) |
| 170 | | body = epage.render(self) |
| 171 | | else: |
| 172 | | epage = resource.ErrorPage(http.NOT_IMPLEMENTED, "Huh?", |
| 173 | | "I don't know how to treat a" |
| 174 | | " %s request." % (self.method,)) |
| 175 | | body = epage.render(self) |
| 176 | | # end except UnsupportedMethod |
| 177 | | |
| | 130 | """ Render a request. |
| | 131 | |
| | 132 | This is called on the leaf resource for |
| | 133 | a request. Render must return either a string |
| | 134 | or a Deferred containing a string as its result. |
| | 135 | This string will be sent to the browser as the HTML |
| | 136 | for the request. |
| | 137 | Render may also return NOT_DONE_YET; if NOT_DONE_YET |
| | 138 | is returned then the resource's render method must |
| | 139 | make any request.write calls and then request.finish. |
| | 140 | Usually these are done in a deffered callback. This |
| | 141 | behaviour will be deprecated in favour of returning |
| | 142 | a Deferred. |
| | 143 | """ |
| | 144 | body = defer.maybeDeferred(resrc.render, self) |
| | 145 | body.addCallbacks(self._cbRender, self._ebRender, |
| | 146 | callbackArgs=(resrc,), errbackArgs=(resrc,)) |
| | 147 | return |
| | 148 | |
| | 149 | def _cbRender(self, body, resrc): |
| | 150 | """ Callback for render; writes the data.""" |
| | 174 | |
| | 175 | def _ebRender(self, fail, resrc): |
| | 176 | """ Errback for render to handle UnsupportedMethod""" |
| | 177 | fail.trap(UnsupportedMethod) |
| | 178 | allowedMethods = fail.value.allowedMethods |
| | 179 | if (self.method == "HEAD") and ("GET" in allowedMethods): |
| | 180 | log.msg("Using GET to fake a HEAD request for %s" % (resrc,)) |
| | 181 | self.method = "GET" |
| | 182 | |
| | 183 | body = defer.maybeDeferred(resrc.render, self) |
| | 184 | body.addCallbacks(self._cbRenderEb, self._ebRenderEb, callbackArgs=(resrc,), errbackArgs=(resrc,)) |
| | 185 | return body |
| | 186 | |
| | 187 | if self.method in (supportedMethods): |
| | 188 | # We MUST include an Allow header |
| | 189 | # (RFC 2616, 10.4.6 and 14.7) |
| | 190 | self.setHeader('Allow', allowedMethods) |
| | 191 | s = ('''Your browser approached me (at %(URI)s) with''' |
| | 192 | ''' the method "%(method)s". I only allow''' |
| | 193 | ''' the method%(plural)s %(allowed)s here.''' % { |
| | 194 | 'URI': self.uri, |
| | 195 | 'method': self.method, |
| | 196 | 'plural': ((len(allowedMethods) > 1) and 's') or '', |
| | 197 | 'allowed': string.join(allowedMethods, ', ') |
| | 198 | }) |
| | 199 | epage = resource.ErrorPage(http.NOT_ALLOWED, |
| | 200 | "Method Not Allowed", s) |
| | 201 | |
| | 202 | body = defer.maybeDeferred(epage.render, self) |
| | 203 | body.addCallback(self._cbRenderEb, resrc) |
| | 204 | return body |
| | 205 | else: |
| | 206 | epage = resource.ErrorPage(http.NOT_IMPLEMENTED, "Huh?", |
| | 207 | "I don't know how to treat a" |
| | 208 | " %s request." % (self.method,)) |
| | 209 | |
| | 210 | body = defer.maybeDeferred(epage.render,self) |
| | 211 | body.addCallback(self._cbRender, resrc) |
| | 212 | return body |
| | 213 | |
| | 214 | def _cbRenderEb(self, body, resrc): |
| | 215 | """ Callback for render's errback; tries to write a fake HEAD request |
| | 216 | that is created from the GET method. |
| | 217 | """ |
| | 218 | if body == NOT_DONE_YET: |
| | 219 | log.msg("Tried to fake a HEAD request for %s, but " |
| | 220 | "it got away from me." % resrc) |
| | 221 | # Oh well, I guess we won't include the content length. |
| | 222 | else: |
| | 223 | self.setHeader('content-length', str(len(body))) |
| | 224 | |
| | 225 | self.write('') |
| | 226 | self.finish() |
| | 227 | return |