Bug 212858 - Request object methods do not work if Request has a body of FormData
Summary: Request object methods do not work if Request has a body of FormData
Status: NEW
Alias: None
Product: WebKit
Classification: Unclassified
Component: JavaScriptCore (show other bugs)
Version: Safari 13
Hardware: Unspecified Unspecified
: P2 Major
Assignee: Nobody
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2020-06-05 18:05 PDT by Peter W
Modified: 2021-11-08 07:17 PST (History)
7 users (show)

See Also:


Attachments
Result from Safari 13 (229.22 KB, image/png)
2020-06-08 15:12 PDT, Peter W
no flags Details
Result from Chrome 83 (325.34 KB, image/png)
2020-06-08 15:13 PDT, Peter W
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Peter W 2020-06-05 18:05:13 PDT
When handling POST requests within application Safari, operations such as text, json, arrayBuffer cause a "NotSupportedError: The operation is not supported". 

When handling POST requests within the developer console in Safari, the same operations do not throw this error.
Comment 1 Peter W 2020-06-05 19:06:19 PDT
As an example, using .text() on a GET and a PUT request does not result in any issues.
Comment 2 Peter W 2020-06-05 19:14:20 PDT
When creating a new POST request within the Safari console using the following example,

var request = new Request('/', {
  method: 'POST',
  body: '{ "foo": "1", "bar": 2 }' 
});

request.json().then(function(json) { 
  console.log(json.foo);
  console.log(json.bar);
});


However in my application when i try to access the request.text(), theres an error that states "NotSupportedError: The operation is not supported" and I'm not sure whats causing this to occur.

function sendRequest(input,requestInit){
    // create request object for POST request
    var request = new Request(input.url, requestInit);
    // trying to read the clone body will throw the above error
    Var requestclone = request.clone().text().then(text=>console.log(text)).catch(err=>console.log(err));

    fetch(request).then(response=>{
        //do stuff here
    });

When running the same function with a GET or a PUT request, the .text() functions works and I run into no issues. The not supported Error only occurs on a POST request.
Comment 3 Alexey Proskuryakov 2020-06-07 13:21:38 PDT
Please provide a complete test case that reproduces the issue. These properties work in general.
Comment 4 Peter W 2020-06-08 15:12:07 PDT
The following is a test case to reproduce the issue where options such as .text(),.arrayBuffer(), .json(), and .formData() do no work. Note when the body is an instance of FormData, the above methods of inspecting the body element are inaccessible and throw a NotSupportError. When the body is a FormData Object, even the .formData() returns a NotSupportedError.

~~~

var formDataObj = new FormData();
formDataObj.append('key','value')


var requestOptions = {
  cache: "default",
  credentials: "same-origin",
  method: "POST",
  mode: "cors"
}
var requestOptionsString = {
  body: "text",
  cache: "default",
  credentials: "same-origin",
  method: "POST",
  mode: "cors"
}
var requestOptionsJSON = {
  body: {"key":"value"},
  cache: "default",
  credentials: "same-origin",
  method: "POST",
  mode: "cors"
}
var requestOptionsFD = {
  body: formDataObj,
  cache: "default",
  credentials: "same-origin",
  method: "POST",
  mode: "cors"
}

function requestTest(input,options){
var request = new Request(input,options)
request.clone().formData().then(formData=>console.log("formData",input,formData)).catch(err=>console.log("noFormData",input,err))
request.clone().json().then(json=>console.log("json",input,JSON.stringify(json))).catch(err=>console.log("noJson",input,err))
request.clone().text().then(text=>console.log("text",input,text)).catch(err=>console.log("noText",input,err))
request.clone().arrayBuffer().then(arrayBuffer=>console.log("arrayBuffer",input,arrayBuffer)).catch(err=>console.log("noArrayBuffer",input,err))
request.clone().blob().then(blob=>console.log("blob",input,blob)).catch(err=>console.log("noBlob",input,err))
fetch(request).then(response=>console.log("response",input,response)).catch(error=>console.log("error",input,error))
}
requestTest('none',requestOptions)
requestTest('string',requestOptionsString)
requestTest('json',requestOptionsJSON)
requestTest('formData',requestOptionsFD)
Comment 5 Peter W 2020-06-08 15:12:38 PDT
Created attachment 401378 [details]
Result from Safari 13
Comment 6 Peter W 2020-06-08 15:13:56 PDT
Created attachment 401379 [details]
Result from Chrome 83

Note, that when the body contains a FormData object, the above functions still return a result such as .text() and .formData() when used in chrome.
Comment 7 Alexey Proskuryakov 2020-06-09 16:44:58 PDT
This is not a complete test, as it lacks its server component. Is there any chance you could set up a test server where this reproduces, for end to end debugging?
Comment 8 Peter W 2020-06-09 17:18:11 PDT
I'm confused why you would need to have a server component for this to be a complete test. The fetch at the end of the test function does not need to be there since it doesn't change the fact that the methods do not have access to the body of the request. The issue is that methods request.text(), request.formData() do not work on a body with FormData in safari 13. In fact, it appears none of the methods for accessing the "body" of the request work when the body is of "formData" type. The request exists within the client side.

Perhaps a better title for the bug would be 
"Request object methods do not work if Request has a body of FormData".
Comment 9 Tom 2020-06-09 22:46:21 PDT
Agree with the suggested new title.

The problem is not to do with *making* the requests but with preparing them.

I think this test captures the issue:

new Request('http://localhost', {method: 'POST', body: new FormData()}).arrayBuffer().then(()=>console.log('success')).catch(err=>console.error('Fail: ' + err.message))

In Safari, this will "fail". In Chrome it will succeed.

The reason I'm here is that Safari 13.1 introduced FormData support in Service Workers (yay, this is good news). But that meant my polyfill deferred to the new native implementation, but the native implementation cannot handle a Request with FormData as the body. The same behaviour is present in the main/UI thread too, so at least things are consistent I guess.

So I'm asking, it would be nice if Request.arrayBuffer() could handle a FormData body :D
Comment 10 Radar WebKit Bug Importer 2020-06-11 18:39:11 PDT
<rdar://problem/64279968>
Comment 11 Philip Jägenstedt 2020-08-31 02:28:11 PDT
Was this fixed in bug 215671?
Comment 12 nyro 2021-11-08 07:17:01 PST
Is it related to bug 187461 ?