Axios: PUT and PATCH sending application/x-www-form-urlencoded data

Created on 3 Aug 2015  Â·  36Comments  Â·  Source: axios/axios

Using 0.5.4

I'm trying to use axios on my front end and fuel on the backend. Fuel Input::patch('param') will give me data from the form request of type patch. This is also true for PUT. Perhaps also POST a.s.o.

When I use axios the data is empty and if I use jquery I get my data just fine.

        $.ajax({
            method: "PATCH",
            url: URL,
            data: {
                'firstname': this.state.account.firstname,
                'surname': this.state.account.surname,
            }
        })
        .done(function( msg ) {
            console.log(msg);
        });
        axios.patch(URL, {
                'firstname': this.state.account.firstname,
                'surname': this.state.account.surname,
            })
            .then((response) => {
                   console.log(response);
            });

The difference is if you look at chrome developer tools that jquery sends the data as formData and axios sends the data as json request payload.

Most helpful comment

How about axios including the above-mentioned serialization code so a Content-Type of application/x-www-form-urlencoded triggers the right encoding when an object is passed?

axios.post(
  '/foo',
  { some: 'data' },
  { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }
);

… should work out of the box IMHO. Or do I miss something?

All 36 comments

I've tried to use formData but this is still sent like a body tag in chrome and not as formData.

Headers

PUT /url/path HTTP/1.1
Host: hostname
Connection: keep-alive
Content-Length: 1234
User-Agent: Mozilla/5.0 
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryJsCvT2m1SBzbA23B
Accept: application/json, text/plain, */*
Referer: URL
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8

Payload

Content-Disposition: form-data; name="firstname"

Daniel
------WebKitFormBoundaryJsCvT2m1SBzbA23B
Content-Disposition: form-data; name="surname"

Persson

Instead of

Headers

PUT /url/path HTTP/1.1
Host: hostname
Connection: keep-alive
Content-Length: 1234
Accept: */*
Origin: http://adminhost
User-Agent: Mozilla/5.0
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: URL
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8

Form data

firstname=Daniel&surname=Persson

If this shouldn't be standard then I think it atleast should be an option to send as form data.

Made a small work around to fix the issue for me.

      config['transformRequest'] = [function (data, headers) {
        var str = [];
        for(var p in data)
          if (data.hasOwnProperty(p) && data[p]) {
            str.push(encodeURIComponent(p) + "=" + encodeURIComponent(data[p]));
          }
        return str.join("&");
      }];

Ran into this also, thank's for the workaround :+1:

@kalaspuffar are we okay to close this?

@mzabriskie

Hi.

I'm currently not working on the project using axios so I can't verify if the new version solves the issue but the workaround works fine for us at the moment.

If the issue is fixed then close. If it won't be then perhaps document a workaround so other don't have to hunt down this post.

But I don't mind closing the issue.

Best regards
Daniel

How about axios including the above-mentioned serialization code so a Content-Type of application/x-www-form-urlencoded triggers the right encoding when an object is passed?

axios.post(
  '/foo',
  { some: 'data' },
  { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }
);

… should work out of the box IMHO. Or do I miss something?

:+1: for supporting x-www-form-urlencoded when the headers is set

+1

Just a quick bit of prior art to add here. The request library uses different keys for body, form (urlencoded, what we're talking about here) and formData (multi-part form uploads). This forces the user to know that these need to be different and to make a choice. I'd love for axios just to just pick a sensible default based on the content-type, but it could be a breaking change if anyone is relying on the older implementation.

@jimthedev You might be right that I've chosen the wrong type of data object.

But the thing I found strange was that a simple GET and POST gave me simple form information in the query way

?ab=CD&ef=gh

using the default send. But PUT and PATCH changed the default to multipart data.

@kalaspuffar Oh I see. Yeah that does seem strange.

+1 x-www-form-urlencoded

Nice

is there any interest in having first-class support for urlencoded put/post baked into axios?

Yes

+1

+1

+1

+1

+1

I think this should be solved by adding support for URLSearchParams. BTW, this has recently been implemented in fetch: https://github.com/github/fetch/commit/d77810a15c78bbbaf2defd4ea3af6db21c8d117f

The only problem is that URLSearchParams is not supported by all browsers, but there is a polyfill.

+1

Glad to see this is in progress

axios v0.12.0 supports URLSearchParams which can be used to send the data as application/x-www-form-urlencoded from the browser:

var params = new URLSearchParams();
params.append('param1', 'value1');
params.append('param2', 'value2');
axios.post('/foo', params); 

Please note that URLSearchParams is not supported by all browsers, so you may need to polyfill it. (Make sure to add the polyfill to the global scope.)

+1 I really need this too, it would be great if the 'urlencoded' could work from within AXIOS just based on the Content-Type.

+1 It should be handled by library. The data parameters should be just object and we don't want to care which request type it is.

+1 still having issues with this.

+1
I used the recommended URLSearchParams polyfill. Still seems to have the issue when using IE11.

Edit:
The problem was caused by cloning the axios config object before it is given to axios for requesting. If the config object contains an instance of URLSearchParams for data in IE11 using the recommended Polyfill then the instance of URLSearchParams in the cloned object is not cloned correctly. It just isn't an URLSearchParams instance any longer.

@kalaspuffar improvement of your function to also parse objects
axios.post(url, {user: { name: 'john' }}, ...) will be encoded as user[name] = john

function jsonToFormEncoded(data, headers) {
  var str = [];
  for(var p in data){
    if(_.isObject(data[p])){
      var d = data[p];
      for(var o in d){
        if (d.hasOwnProperty(o) && d[o]) {
          str.push(p+'['+encodeURIComponent(o) + "]=" + encodeURIComponent(d[o]));
        }
      }
    }else{
      if (data.hasOwnProperty(p) && data[p]) {
        str.push(encodeURIComponent(p) + "=" + encodeURIComponent(data[p]));
      }
    }
  }
  return str.join("&");
}

Having the same Issue. Using OWIN middleware and since the axios.put request sends raw JSON I cant handle it correctly.

Still having issues. Surprised it hasnt been fixed since its such a core feature?

+1

This thing is really annoying. Having to install a polyfill seems just too much, Axios should take care of this transparently. Such problems make people look for other libraries instead.

i use this interceptor, which works quite well.

Vue.axios.interceptors.request.use((config) => {
    if (config.headers['Content-Type'] && config.headers['Content-Type'] === 'application/x-www-form-urlencoded') {
      config.transformRequest = (data) => {
        const str = [];
        Object.keys(data).forEach(key => str.push(`${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`));
        return str.join('&');
      };
    }

    return config;
  }, error => Promise.reject(error));

@kalaspuffar -s code as default config, thank you it works now!

```

axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
axios.defaults.transformRequest = [function (data, headers) {
var str = [];
for(var p in data)
if (data.hasOwnProperty(p) && data[p]) {
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(data[p]));
}
return str.join("&");
}];

Year later and it is still issue. (And why it is closed?)

Even URLSearchParams is not covering entire problem.

Now i want to send FormData object, by PATCH. And what should i do?

jQuery has this from the box a lot of years ago. But axios can't recognize formData

Was this page helpful?
0 / 5 - 0 ratings

Related issues

adl1995 picture adl1995  Â·  143Comments

youurayy picture youurayy  Â·  69Comments

burakuluu picture burakuluu  Â·  58Comments

j-planet picture j-planet  Â·  70Comments

corujoraphael picture corujoraphael  Â·  46Comments