Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Edge/IE fail to set Content-Type header on XHR whose body is a typed Blob #44

Closed
balessan opened this issue Dec 3, 2017 · 24 comments
Closed

Comments

@balessan
Copy link

balessan commented Dec 3, 2017

Hello Jimmy,

I am using your polyfill on my current project to be able to use the FormData object on IE 11, and it seems good until the request is actually processed by the server.

Working on a PHP back-end, when I var_dump the request Body I got something which looks like the following:

------formdata-polyfill-0.66513968191100183ContentDispositionform-dataname=emailben@toto.fr------formdata-polyfill-0.66513968191100183ContentDispositionform-dataname=password------

And so on. Obviously this body seems badly-formed.
I am using your polyfill by requiring it from my main JS entry file:

require("formdata-polyfill");

window.app = new (function()
{
     ...

And to submit my form I am using the following code:

if ( ! formData )
{
  var formData = new FormData( _.formInstance );
}

var xhr = new XMLHttpRequest();

xhr.open( method, url );

xhr.setRequestHeader( "X-Requested-With", "XMLHttpRequest" );

xhr.send( formData );

The content of formData is ok at this point ( I displayed the key value content to be sure ). So I am not sure of the source of the issue. Any Idea ?

It's blocking for me right now, as I cannot get the complete support of my app on IE 11...

Let me know ;-)

@jimmywarting
Copy link
Owner

jimmywarting commented Dec 3, 2017

hmm, it do look badly formatted. Could you try to dump the actual blob that are being sent using this client side code?
here is how

var blob = formdata._blob() 
var fr = new FileReader
fr.onload = function() {
  console.log(fr.result)
}
fr.readAsText(blob)

for me it looks something like:

------formdata-polyfill-0.24730354822730538
Content-Disposition: form-data; name="key"

value
------formdata-polyfill-0.24730354822730538--

which is correct.

Would also help if you dumped the request headers... specifically the content-type header you get in your server

@balessan
Copy link
Author

balessan commented Dec 3, 2017

Using the code you provided I got the following ( see the screenshot as I am testing using BrowserStack and cannot copy/paste easily ), which looks ok.

So then it's an issue on the backend side.Is that possible that the formdata-polyfill prefix is conflicting with the form entry parsing library of my current framework ?

Hum...
capture d ecran de 2017-12-03 15-30-31

@jimmywarting
Copy link
Owner

Got to be a problem on the server side...
Are you using a library for parsing multipart forms?

Things you can check:

  • Are the the blob size the same as Content-Length request header?
  • Are the Content-Type request header same as the blob's mime type?

PHP should be able to parse it $_POST["email"]

@balessan
Copy link
Author

balessan commented Dec 3, 2017

I'll check that ;-)

@jimmywarting
Copy link
Owner

jimmywarting commented Dec 3, 2017

chromes FormData don't look much different

fd = new FormData
fd.append('key', 'value')
new Response(fd).text().then(console.log)

result = `
------WebKitFormBoundary9F5Xu977y9H9FXm0
Content-Disposition: form-data; name="key"

value
------WebKitFormBoundary9F5Xu977y9H9FXm0--
`

note: Math.random is not always the same length
So calling fd._blob() might not be the same size when you are sending it.

so you can instead send the blob... xhr.send(blob)

@balessan
Copy link
Author

balessan commented Dec 3, 2017

What seems strange is that the developer tools of my IE11 borwserStack instance are not detecting anything in the request body, even though the code you gave me seems ok. See the following screen for reference.

It really looks to me that the HTTP Post is send empty.

capture d ecran de 2017-12-03 15-57-15

@jimmywarting
Copy link
Owner

I'm not sure how you can miss something like a -, spaces and ; in your body. Something is stripping the content

@jimmywarting
Copy link
Owner

jimmywarting commented Dec 3, 2017

Weird. try sending the blob then and see what happens... xhr.send(formdata._blob())
the content-type header is wrong, but it might also be the response content-type and not the request content-type

the polyfill also got another trick in the sleeve, formdata = formdata._asNative()

@jimmywarting
Copy link
Owner

mather of fact, it looks to me like you are inspecting the response body, response header & the response content-type

@balessan
Copy link
Author

balessan commented Dec 3, 2017

Ok on the client side I was missing the Content-Type : multipart/form-data which explains the emptyness of the request body when inspecting.

Remaining issue is on the backend side.

Thanks for your attention, I have been making some progress ;-) And your library has no issue then.

@balessan balessan closed this as completed Dec 3, 2017
@jimmywarting
Copy link
Owner

jimmywarting commented Dec 3, 2017

Was snooping around on browserstack myself when you reveled your website.
It doesn't look like the Content-Type is being set?

If you would perhaps do it like this:

var blob = formdata._blob();

xhr.open( method, url );
xhr.setRequestHeader( "X-Requested-With", "XMLHttpRequest" );
xhr.setRequestHeader( "Content-Type", blob.type );
xhr.send( blob );

would it work for you then?

@jimmywarting
Copy link
Owner

In that case i might make a patch where i set the content-type header in the polyfill

@balessan
Copy link
Author

balessan commented Dec 3, 2017

I am testing.

@jimmywarting
Copy link
Owner

The spec is: If you are sending a Blob/file with ajax and no content-type header is specified it should use the Files type as content-type. IE don't seems to follow that rule?

@balessan
Copy link
Author

balessan commented Dec 3, 2017

Yes I can confirm your patch works fine.

Stupid IE.

@jimmywarting
Copy link
Owner

Gah, hate IE. Going to make a patch to fix it.

@jimmywarting
Copy link
Owner

@balessan
Copy link
Author

balessan commented Dec 3, 2017

Top ! And really thanks for your time ;-)

@jimmywarting jimmywarting reopened this Dec 3, 2017
@balessan
Copy link
Author

balessan commented Dec 3, 2017

I am not that familiar with the use of Blobs so I did not look in that direction but yeah, your article seems to correspond to the situation.

@jimmywarting jimmywarting changed the title Corrupted content of the request Body Edge/IE fail to set Content-Type header on XHR whose body is a typed Blob Dec 3, 2017
@jimmywarting
Copy link
Owner

jimmywarting commented Dec 3, 2017

Fixed in 3.0.6 3.0.7

@balessan
Copy link
Author

balessan commented Dec 3, 2017

👍

@balessan
Copy link
Author

balessan commented Dec 3, 2017

Tested but got an issue being:

Object doesn't support property or method 'a'

The incriminated line being:

XMLHttpRequest.prototype.send=function(b){b instanceof H&&(b=b.a(),this.setRequestHeader("Content-Type", b.type))

@jimmywarting
Copy link
Owner

Forgot closure compiler mangels private properties/methods starting with _
Fixed in 3.0.7

@balessan
Copy link
Author

balessan commented Dec 3, 2017

Works perfect !

@jimmywarting jimmywarting mentioned this issue Jul 24, 2018
macobo added a commit to PostHog/posthog that referenced this issue Feb 3, 2021
When posting gzipped data from posthog-js (gzip-js), all browsers except
IE11 send content-type as 'text/plain'. IE11 has a bug
(jimmywarting/FormData#44) where it fails to
do that, causing us to dismiss these events.

This only occurs when using bin/docker-server and not bin/start-backend.

Related PR: PostHog/posthog-js#180
macobo added a commit to PostHog/posthog that referenced this issue Feb 3, 2021
When posting gzipped data from posthog-js (gzip-js), all browsers except
IE11 send content-type as 'text/plain'. IE11 has a bug
(jimmywarting/FormData#44) where it fails to
do that, causing us to dismiss these events.

This only occurs when using bin/docker-server and not bin/start-backend.

Related PR: PostHog/posthog-js#180
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants