How to Post a X-Www-Form-Urlencoded Request Using Fetch

How do I POST a x-www-form-urlencoded request using Fetch?

You have to put together the x-www-form-urlencoded payload yourself, like this:

var details = {
'userName': 'test@gmail.com',
'password': 'Password!',
'grant_type': 'password'
};

var formBody = [];
for (var property in details) {
var encodedKey = encodeURIComponent(property);
var encodedValue = encodeURIComponent(details[property]);
formBody.push(encodedKey + "=" + encodedValue);
}
formBody = formBody.join("&");

fetch('https://example.com/login', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
},
body: formBody
})

Note that if you were using fetch in a (sufficiently modern) browser, instead of React Native, you could instead create a URLSearchParams object and use that as the body, since the Fetch Standard states that if the body is a URLSearchParams object then it should be serialised as application/x-www-form-urlencoded. However, you can't do this in React Native because React Native does not implement URLSearchParams.

POST Request in Body as x-www-form-urlencoded

You are mixing things up. Those parameters grant_type, client_id, client_secret and refresh_token are not HTTP-Headers but the payload that you're sending to the server.

According to the docs (https://developers.google.com/apps-script/reference/url-fetch/url-fetch-app), this should work:

var cisurl = "https://webexapis.com/v1/access_token";

var data = {
'grant_type': 'refresh_token',
'client_id': 'abcdefg',
'client_secret': 'hijklmn',
'refresh_token': 'opqrstuvw'
};

var options = {
'method': 'post',
'payload': data
}

var response = UrlFetchApp.fetch(cisurl,options);

P.S.: Do not share your secrets on stack-overflow

How to post a x-www-form-urlencoded data properly using javascript?

You're building an array of encoded name/value pairs and passing that directly as the body of the POST. But fetch doesn't accept an array in that parameter.

The minimal change to your code would be to join the array using & as the separator:

return fetch(
`${serverAddress}/api/shopProducts`,
{
method: 'POST',
body: formBody.join("&"), // <===== here
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}
). /* etc */

Alternately, use FormData, as this is exactly what it's for: :-)

getInsideMenu(categoryid,shopid){
var formBody = new FormData();
formBody.set("categoryId", categoryid);
formBody.set("shopId", shopid);
formBody.set("page", "0");
return fetch(
`${serverAddress}/api/shopProducts`,
{
method: 'POST',
body: formBody,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}
).then((res)=>(res.json()));
}

(Depending on your needs, you might use set or append. The above uses set.)


Side note 1:

This line:

).then((res)=>(res.json()));

...doesn't need most of those ():

).then(res => res.json());

Side note 2:

Don't forget to check for success; failing to do so is a common pitfall when using fetch. fetch doesn't reject on HTTP error (like 404 or 500). If you want to reject on HTTP error, you have to do it yourself:

return fetch(/*...*/)
.then(res => {
if (!res.ok) {
throw new Error(res.status);
}
return res;
})
.then(res => res.json());

How do I post form data with fetch api?

To quote MDN on FormData (emphasis mine):

The FormData interface provides a way to easily construct a set of key/value pairs representing form fields and their values, which can then be easily sent using the XMLHttpRequest.send() method. It uses the same format a form would use if the encoding type were set to "multipart/form-data".

So when using FormData you are locking yourself into multipart/form-data. There is no way to send a FormData object as the body and not sending data in the multipart/form-data format.

If you want to send the data as application/x-www-form-urlencoded you will either have to specify the body as an URL-encoded string, or pass a URLSearchParams object. The latter unfortunately cannot be directly initialized from a form element. If you don’t want to iterate through your form elements yourself (which you could do using HTMLFormElement.elements), you could also create a URLSearchParams object from a FormData object:

const data = new URLSearchParams();
for (const pair of new FormData(formElement)) {
data.append(pair[0], pair[1]);
}

fetch(url, {
method: 'post',
body: data,
})
.then(…);

Note that you do not need to specify a Content-Type header yourself.


As noted by monk-time in the comments, you can also create URLSearchParams and pass the FormData object directly, instead of appending the values in a loop:

const data = new URLSearchParams(new FormData(formElement));

This still has some experimental support in browsers though, so make sure to test this properly before you use it.

ASP.NET Core Fetch POST FormData() application/x-www-form-urlencoded

Since you are sending data using FormData the Content-Type of your request should be application/form-data. But as you can see in browser network tab there is some strange values between the actual data values

-----WebKitFormBoundarySomeValue

This is a boundary separating your data entries. And the actual value of Content-Type header should be application/form-data; boundary=-----WebKitFormBoundarySomeValue. Since this value is generated randomly by a browser you cannot set it manually and you should just omit Content-Type header, browser will set it for you.

headers: {
"Accept": "application/json, application/xml, text/plain, text/html, *.*"
//no content-type
}

In your controller code use [FromForm] attribute to read request data as form data. And you should abandon using Consumes attribute in this case since you cannot specify correct Content-Type value because it varies between requests.

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login([FromForm]LoginModel model)


Related Topics



Leave a reply



Submit