Debug a POST With a Stream Body That Hangs After a 307 Redirect in Python Requests

Read the full interview experience this question came from →

Quick Overview

A debugging exercise in the Python Requests library: a POST with a file-like body hangs after a 307 Temporary Redirect until the client times out. It tests reasoning about the bytes on the wire, HTTP redirect semantics, stream state across a re-sent request, and writing a deterministic regression test.

Debug a POST With a Stream Body That Hangs After a 307 Redirect in Python Requests

Company: Stripe

Role: Software Engineer

Category: Software Engineering Fundamentals

Difficulty: medium

Interview Round: Technical Screen

You are given a working copy of **Requests**, the widely used Python HTTP client library, into which a bug has been planted. One bug is reported for this repository, though the report is not certain it is the only one. Assume a reproduction shows the following. A client sends a `POST` whose body is a file-like object, such as `io.BytesIO(b"amount=100")`, to a URL that answers `307 Temporary Redirect` with a `Location` header. Requests follows the redirect automatically, but the request to the new location never completes: it waits until the client's read timeout fires, or forever if no timeout is set. The same `POST` with a plain `bytes` body completes normally, and so does the file-like body when the server does not redirect. Explain exactly why the redirected request hangs, find the root cause in the library, fix it, and prove the fix with a regression test. ```hint Look at what goes over the wire Compare what the redirected request's headers promise with the bytes the client actually sends after them, and ask what each side is waiting for. ``` ```hint Same request, second send Ask what a file-like body remembers between two sends that a bytes body does not, and which part of the library is responsible for it before the request goes out again. ``` ### Constraints and Clarifications - Change only the library and its tests; the redirecting server behaves correctly. - Requests follows redirects for `POST` by default; keep that behavior. - The body in the reproduction is seekable and its length is known up front, so it is sent with a `Content-Length` header. ### Clarifying Questions - Does the same hang occur for `308 Permanent Redirect`, and for `301`, `302` and `303`? - What should happen on a redirect when the body cannot be rewound, for example a generator or a pipe? - If the stream was not at its start when the request was made, which bytes should the redirected request send? - Should a redirect to a different host re-send the body at all? ### What a Strong Answer Covers - A precise explanation of the hang: what each side sends and waits for, and why it ends in a timeout instead of an error - How the body's state was traced through preparing, copying and re-sending the request - A fix at the layer that re-sends the request, covering streams that start mid-way and streams that cannot be restored - Why only some redirect status codes expose the bug - A regression test that reproduces the original failure quickly and deterministically, without hanging the test suite ### Follow-up Questions - The body is a generator that yields chunks. What should Requests do when the server answers `307`? - A teammate proposes recomputing `Content-Length` from the stream before re-sending. It stops the hang. Why is it still wrong? - On a `307` to a different host, which headers should Requests keep, and which must it drop? - How would you test this without opening sockets, and what would that test no longer prove?

Overview: A debugging exercise in the Python Requests library: a POST with a file-like body hangs after a 307 Temporary Redirect until the client times out. It tests reasoning about the bytes on the wire, HTTP redirect semantics, stream state across a re-sent request, and writing a deterministic regression test.

Read the full Stripe Software Engineer interview experience this question came from

|Home/Software Engineering Fundamentals/Stripe
Stripe logo
Stripe
Oct 14, 2026
mediumSoftware EngineerTechnical ScreenSoftware Engineering Fundamentals
0
0

You are given a working copy of Requests, the widely used Python HTTP client library, into which a bug has been planted. One bug is reported for this repository, though the report is not certain it is the only one. Assume a reproduction shows the following.

A client sends a POST whose body is a file-like object, such as io.BytesIO(b"amount=100"), to a URL that answers 307 Temporary Redirect with a Location header. Requests follows the redirect automatically, but the request to the new location never completes: it waits until the client's read timeout fires, or forever if no timeout is set. The same POST with a plain bytes body completes normally, and so does the file-like body when the server does not redirect.

Explain exactly why the redirected request hangs, find the root cause in the library, fix it, and prove the fix with a regression test.

Constraints and Clarifications

  • Change only the library and its tests; the redirecting server behaves correctly.
  • Requests follows redirects for POST by default; keep that behavior.
  • The body in the reproduction is seekable and its length is known up front, so it is sent with a Content-Length header.

Clarifying Questions Guidance

  • Does the same hang occur for 308 Permanent Redirect , and for 301 , 302 and 303 ?
  • What should happen on a redirect when the body cannot be rewound, for example a generator or a pipe?
  • If the stream was not at its start when the request was made, which bytes should the redirected request send?
  • Should a redirect to a different host re-send the body at all?

What a Strong Answer Covers Guidance

  • A precise explanation of the hang: what each side sends and waits for, and why it ends in a timeout instead of an error
  • How the body's state was traced through preparing, copying and re-sending the request
  • A fix at the layer that re-sends the request, covering streams that start mid-way and streams that cannot be restored
  • Why only some redirect status codes expose the bug
  • A regression test that reproduces the original failure quickly and deterministically, without hanging the test suite

Follow-up Questions Guidance

  • The body is a generator that yields chunks. What should Requests do when the server answers 307 ?
  • A teammate proposes recomputing Content-Length from the stream before re-sending. It stops the hang. Why is it still wrong?
  • On a 307 to a different host, which headers should Requests keep, and which must it drop?
  • How would you test this without opening sockets, and what would that test no longer prove?