jerrybendy / url-search-params-polyfill

a simple polyfill for javascript URLSearchParams
MIT License
599 stars 89 forks source link

Fetch API fails to set Content-Type automatically #18

Open thw0rted opened 6 years ago

thw0rted commented 6 years ago

I have some code along the lines of

let params = new URLSearchParams(...);
let opts = {
  method: "post",
  body: params,
  credential: "same-origin",
};
fetch(url, opts).then(...);

I used this polyfill to get the URLSearchParams constructor working in Edge. This is fine, but in Chrome and Firefox, setting the POST body to a URLSearchParams instance also sets the Content-Type header to application/x-www-form-urlencoded, per the Fetch spec. When using the polyfill, I have to manually set this header value in each Fetch call, using headers in the options object.

It would be great if the polyfill could hook/patch the fetch method to set this value automatically, but I suspect this won't be feasible. In that case, the documentation should be updated to note this additional usage requirement. Ideally, the library could expose a feature test function or a global variable that we could test against before manually setting headers:

if (__URLSEARCHPARAMS_USE_POLYFILL){
  opts.headers = {"Content-Type": "application/x-www-form-urlencoded; charset=utf-8"}
}

rather than always overriding the automatically-determined (in fully compliant browsers) content type.

jerrybendy commented 6 years ago

Do you use the latest version of this library? The latest version now is 2.0.1.

In fact, I have added this feature on 20 Jul, 2017. Refer to commit https://github.com/jerrybendy/url-search-params-polyfill/commit/23745279a29031031a2acd24e8a68911ef25691c

    /*
     * Apply polifill to global object and append other prototype into it
     */
    self.URLSearchParams = (nativeURLSearchParams && !isSupportObjectConstructor) ?
        new Proxy(nativeURLSearchParams, {
            construct: function(target, args) {
                return new target((new URLSearchParamsPolyfill(args[0]).toString()));
            }
        }) :
        URLSearchParamsPolyfill;

As the code above, I added a Proxy to extend the native URLSearchParams if it has no full feature support.

You can try to update your library to the latest version and try again. If your problem not fixed, please add a comment to this issue and detail which browser and which version you tested.

thw0rted commented 6 years ago

I just added the polyfill from NPM a few hours ago, double checked and it is definitely v2.0.1. The problem I described above is in the current version of Edge, so, 16 I think? I don't have the test system in front of me, I can double check Edge version if important.

I'm not clear on how the commit you've linked to is supposed to address the problem I ran into with fetch.

jerrybendy commented 6 years ago

I checked on caniuse, and Edge 16 supports fetch natively, but it doesn't support URLSearchParams. Browsers which both support fetch and URLSearchParams will add a Content-Type: application/x-www-form-urlencoded; charset=utf-8 header to the request. Because of not support URLSearchParams, Edge 16 will not add this header to the request. So it causes your issue.

thw0rted commented 6 years ago

Yes, right, that's what I meant -- this shortcoming should be in the polyfill's documentation, and the workaround/fix would be cleaner if the polyfill exposed nativeURLSearchParams globally (which, again, would need to be documented).

jerrybendy commented 6 years ago

As what you said, it won't be feasible to patch the fetch function. I will update the document to explain about this.

And I think... maybe it should expose a property (or anything else) to help checking whether the bowser supports URLSearchParams natively or not, if I can't come up with a better idea to solve this issue...

jerrybendy commented 6 years ago

I've added known issues to the documentation to explain this issue and release a new version.

I discovered that there are so many browsers don't both support fetch and URLSearchParams, and they don't support Proxy, too. So it's difficult to extend the native fetch method.

iaincollins commented 6 years ago

Thanks for the library! This comment should possibly be a separate ticket, but just to say in the README it says this in relation to this issue:

Use with fetch (#18)
Via fetch spec, when passing an URLSearchParams object as a request body, the request should add a header with Content-Type: application/x-www-form-urlencoded; charset=UTF-8. But, browsers which have fetch support but no URLSearchParams have no this behavior.

Via the data of caniuse, there are many browsers support fetch but URLSearchParams. They are:

I think there is a typo in the first sentence and it's not clear exactly what it's trying to explain.

Would be great if someone could clarify. Thanks!

jerrybendy commented 6 years ago

@iaincollins You can read the latest version of document here

My English is not so good, and the document has corrected by @ryuhhnn in #23

rahul-rautwar commented 5 years ago

I am using this polyfill, its working fine for Edge v40 but not on IE 11, I am getting this error msg in console: "Error: unsupported BodyInit type" Can someone suggest me how can I made it to work on IE11

thw0rted commented 5 years ago

Rahul, does that have anything to do with the Content-Type problem described in this issue? You might need to create a new issue to track your problem. (I noticed that the README does not list what versions of browsers are supported by the polyfill, or at least what versions have been tested -- might be nice to have!)