Fetch: How to make a post request with JSON data in application/x-www-form-urlencoded

Created on 18 Jan 2016  路  21Comments  路  Source: github/fetch

let data = {
    a: "some data",
    b: 33,
    c: [
        {
            name: "XYZ",
            other: true
        },
        {
            name: "ABC",
            other: true
        }
    ]
    d: {
        something: true
    }
}

How to make a POST request with above JSON data, as content-type application/x-www-form-urlencoded using fetch api?

Most helpful comment

That makes sense.

Too bad we need yet another polyfill for that to work..

import URLSearchParams from 'url-search-params';

const searchParams = new URLSearchParams();
for (const prop in params) {
  searchParams.set(prop, params[prop]);
}


fetch(url, {
  method: 'POST',
  body: searchParams
})

And that only works for flat objects..

And than again, when the data is that simple, a manual conversion isn't that hard as well.

const searchParams = Object.keys(params).map((key) => {
  return encodeURIComponent(key) + '=' + encodeURIComponent(params[key]);
}).join('&');

fetch(url, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
  },
  body: searchParams
})

Thanks for the quick reply and the insight!

All 21 comments

You need to serialize it yourself to a string. If you're using jQuery, then you can use $.param(data) to serialize it. Don't forget to specify the Content-type header for the request.

However, if your server accepts JSON, it would be much easier to just JSON.stringify(data) and post JSON instead.

Anyway, we can't help you with details about communicating with your server. The fetch() standard itself doesn't handle any encoding strategies. It's all left to the user.

Thanks @mislav

Server can't accept JSON data, that is the all problem. I'm trying to solve this with out jquery. Any suggestion?

I can't solve this problem for you. You could take a look at Zepto's $.param implementation and try to copy it. You would have to rewrite it a little bit to not make it dependent on $.isFunction, $.isArray, $.type and $.each.

You might also consider using FormData as the post body. Server endpoints that accept application/x-www-form-urlencoded frequently accept multipart/form-data as well.

:+1:

For anyone else who might still have this problem, I've implemented mislav suggestion using lodash here:
https://gist.github.com/yakirn/831e5e7fcdfb50fc6c94
It needs more testing, so i'll appreciate any feedback.

@dgraham using

fetch(url, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded'
    },
    body: new FormData(postData)
})

results in this formData why I try it...


image

A FormData request body automatically sets the Content-Type to multipart/form-data. Overriding the header with a different type, like in the above example, probably won't work.

A URLSearchParams request body automatically sets the Content-Type header to application/x-www-form-urlencoded;charset=UTF-8.

https://fetch.spec.whatwg.org/#body-mixin

That makes sense.

Too bad we need yet another polyfill for that to work..

import URLSearchParams from 'url-search-params';

const searchParams = new URLSearchParams();
for (const prop in params) {
  searchParams.set(prop, params[prop]);
}


fetch(url, {
  method: 'POST',
  body: searchParams
})

And that only works for flat objects..

And than again, when the data is that simple, a manual conversion isn't that hard as well.

const searchParams = Object.keys(params).map((key) => {
  return encodeURIComponent(key) + '=' + encodeURIComponent(params[key]);
}).join('&');

fetch(url, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
  },
  body: searchParams
})

Thanks for the quick reply and the insight!

@tiemevanveen Thanks for simple urlencoder :)

@tiemevanveen Thanks

How I solved this:

I am using "qs" package for stringifying/encoding the json

My Request code:

        fetch('http://localhost:8888/oauth2/token',
        {
          method: 'POST',
          headers: {
            'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
          },
          body: qs.stringify({
            grant_type: 'password',
            username: 'user_name',
            password: "user_password"
          })
        })

this makes server call as

image

I got this working by using JSON.stringify and the correct headers:
image

@nitinja This solved it for me! Thanks a lot

enable to get data should get the data in the array of books
fetch('https://reactnd-books-api.udacity.com/search', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Authorization': 'whatever-you-want',
'Content-Type': 'application/json'
},
body: JSON.stringify({ query, maxResults })
}).then(res => res.json())
.then(data => console.log(data))

@nitinja
can use qs in React ?

Where can I get help on fetch?

This is how I solved for that issue. It was also a problem in jsfiddles echo. I got lazy and used jQuery in the end. Hope this helps others. https://jsfiddle.net/6mnk6kkq/

function GetSomeDeferredStuff() {
  var deferreds = [];
  for (let count = 1; count <= 10; count++) {
    var params = {
      html: '<p>Task #'+count+' complete.',
      delay: count
    }

   //Encode the data
   const searchParams = Object.keys(params).map((key) => {
     return encodeURIComponent(key) + '=' + encodeURIComponent(params[key]);
   }).join('&');

    //Push fetch requests to an array
    deferreds.push(
      fetch("/echo/html/",
      {
          method: "POST",
          headers: {
            'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
          },
          body: searchParams
      })
      .then(r => r.text())
      .then(data => log(data))
    );
  }
  return deferreds;
}

//  Log for debugging
function log(html){
    console.log(html);
    $("div").append(html);
}

// Execute using jQuery or Promise.All() if preferred
$(function() {
    $("a").click(function() {
        var deferreds = GetSomeDeferredStuff();

        $.when.apply($, deferreds).done(function(e,i) {
            $("div").append("<p>All done!</p>");
        });
    });
});

@nitinja Thanks a lot

I have problem with post request authentification while trying to run the code I get error invalide request does anyone know how I could solve this problem, I get this error { error: 'invalid_request' }

const dat = {
'grant_type': 'authorization_code',

          'code':code ,
           "redirect_uri" : redirect
           };

const URLSearchParams = Object.keys(dat).map((key) => {
return encodeURIComponent(key) + '=' + encodeURIComponent(dat[key]);
}).join('&');

fetch('https://polarremote.com/v2/oauth2/token',
{

method: 'POST',
headers: {
'Authorization':Basic ${creds},

'Content-Type': 'application/x-www-form-urlencoded',
 'Accept':'application/json; charset=utf-8'

},
data: URLSearchParams

}).then(function(res) {
return res.json();
}).then(function(body) {
console.log(body);
});

@nitinja I wish I had seen ur post sooner!! been fiddling around with fetch for a week now trying to firgure out if I did the body formatting wrong cos I can't get the API to recognize the body of my request and now finally it's working! YOU'RE A LIFE SAVER!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

poppinlp picture poppinlp  路  4Comments

DimitryDushkin picture DimitryDushkin  路  4Comments

huanghaiyang picture huanghaiyang  路  3Comments

proofrock picture proofrock  路  3Comments

shirotech picture shirotech  路  3Comments