twisted / twisted/klein

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

Open
#71 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
Python
Stars
838
Forks
123
Avg merge
7h 58m
Merged PRs (30d)
12

Description

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.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in klein/resource.py at processing_failed, especially the response handling around lines 234-241, and review the linked Werkzeug RequestRedirect behavior. Reproduce a trailing-slash redirect and verify that the status, headers, Content-Length, and body describe the same response and that curl completes without hanging.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.