klein
klein copied to clipboard
Incorrect body/headers returned when werkzeug.router raises a redirect
As of v10.0, werkzeug.routing
raises a RequestRedirect
(subclass of HTTPException
) when you pass an URL without a trailing slash, trying to redirect it to the corresponding canonical URL with the slash.
However, what appears to me to be a bug in Flask's error handler causes the returned redirect response to have mismatching body and headers:
-
werkzeug.routing
raisesRequestRedirect
(wkz/routing.py:1421) -
RequestRedirect
is subclass ofHTTPException
but overridden to return a customizedResponse
, as created by theredirect
helper function. (wkz/utils.py:338) - The exception bubbles up through Klein's
Deferred
, and eventually ends up in the failure handlerprocessing_failed
. (klein/resource.py:220) - The handler checks for a
HTTPException
and then starts to propagate it up to response. (klein/resource.py:234) - However, instead of setting everything using the response object obtained by calling
he.getResponse()
, it takes only the headers from it. The error code and body are taken directly from the exception withhe.get_body()
. - The
HTTPException.get_body
method is programmed to return a fixed string depending on the error code represented by the class. It ignores the overriddengetResponse
fromRequestRedirect
. (wkz/exceptions.py:113) - The headers set in klein/resource.py:238 and the body returned in klein/resource.py:241 mismatch.
Notably, the headers of the RequestRedirect
response include Content-Length
of the original message. With the request actually returning a different body, with a different actual length, this causes problems. For example, curl will hang forever, trying to read all the bytes which the header says the response has, but will never arrive.
I guess the quickest way forward for now would be to depend on werkzeug <10?
That would get rid of this specific issue with the auto-redirects. (in my case I just fixed the offending curl invocation to add the missing slash at the end, since I control both ends...) I think there will still be issues for any other redirects that are handled via exceptions.
I don't think properly fixing it (Basically, only the Response
returned by getResponse
be used to se the attributes for the client's response.) would be very hard, but I don't know Werkzeug or the Twisted http interfaces well enough to do that fix.
Digging into resource.py
as of version 15.1, the body/headers mismatch bug appears to still be present.