klein icon indicating copy to clipboard operation
klein copied to clipboard

Incorrect body/headers returned when werkzeug.router raises a redirect

Open yuriks opened this issue 10 years ago • 3 comments

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 raises RequestRedirect (wkz/routing.py:1421)
  • RequestRedirect is subclass of HTTPException but overridden to return a customized Response, as created by the redirect helper function. (wkz/utils.py:338)
  • The exception bubbles up through Klein's Deferred, and eventually ends up in the failure handler processing_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 with he.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 overridden getResponse from RequestRedirect. (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.

yuriks avatar Feb 20 '15 04:02 yuriks

I guess the quickest way forward for now would be to depend on werkzeug <10?

hynek avatar Feb 20 '15 10:02 hynek

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.

yuriks avatar Feb 20 '15 15:02 yuriks

Digging into resource.py as of version 15.1, the body/headers mismatch bug appears to still be present.

brighid avatar Sep 09 '15 05:09 brighid