fetch icon indicating copy to clipboard operation
fetch copied to clipboard

[Question] What is the expected behavior for reusing the Request body in a HTTP redirect fetch (status code 307 / 308)?

Open ytxmobile98 opened this issue 2 years ago • 4 comments

I am performing maintenance work for some some internal implementation of the fetch API for the company I am working in. Recently I discovered some bugs of that implementation related to HTTP redirect fetches with a POST request and a 3xx return code, and I am working on fixing them.

The typical use case is as follows:

  1. The user makes a POST request to xxx.com with a body 12345
  2. xxx.com returns a 3XX return code and the new URL yyy.com to redirect to
  3. The user then requests yyy.com with the POST request and the same body 12345

My major confusion arises when I discovered bugs related to the 307 and 308 return codes.

Basically, MDN says this for 307:

The only difference between 307 and 302 is that 307 guarantees that the method and the body will not be changed when the redirected request is made.

And for 308:

The request method and the body will not be altered, whereas 301 may incorrectly sometimes be changed to a GET method.

But the Fetch Spec suggests otherwise:

  1. If internalResponse’s status is not 303, request’s body is non-null, and request’s body’s source is null, then return a network error.

This is my interpretation:

  • For 307 and 308 status codes, MDN suggests that the same method and same body shall be used for the subsequent access to the redirected URL.
  • But in fetch spec, if I follow the "HTTP-redirect fetch" item 11 (as given above), then it would end up in network error.

So my question arises here: What is the expected behavior for reusing the Request body in a HTTP redirect fetch (307 / 308 return codes)?

ytxmobile98 avatar May 26 '23 09:05 ytxmobile98

The behavior you quote above is what happens for request body streams. And we do that because they cannot be replayed without storing the whole request body in memory, which is something we decided against doing as that would have negative performance implications in the common case.

annevk avatar May 26 '23 09:05 annevk

It might not be a bad idea to add a note there clarifying that.

annevk avatar May 26 '23 09:05 annevk

The behavior you quote above is what happens for request body streams. And we do that because they cannot be replayed without storing the whole request body in memory, which is something we decided against doing as that would have negative performance implications in the common case.

request’s body is non-null

In real use cases, can this body be some stateless data such as strings, ArrayBuffers or Blobs? If yes, does the same logic and decision still make sense?

ytxmobile98 avatar May 26 '23 09:05 ytxmobile98

Yes it can, but then its source would not be null.

annevk avatar May 26 '23 09:05 annevk