I have some parameters that I want to POST form-encoded to my server:
{
'userName': 'test#gmail.com',
'password': 'Password!',
'grant_type': 'password'
}
I'm sending my request (currently without parameters) like this
var obj = {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
},
};
fetch('https://example.com/login', obj)
.then(function(res) {
// Do stuff with result
});
How can I include the form-encoded parameters in the request?
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.
Even simpler:
fetch('https://example.com/login', {
method: 'POST',
headers:{
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({
'userName': 'test#gmail.com',
'password': 'Password!',
'grant_type': 'password'
})
});
Docs: https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch
Use URLSearchParams
https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams
var data = new URLSearchParams();
data.append('userName', 'test#gmail.com');
data.append('password', 'Password');
data.append('grant_type', 'password');
Just did this and UrlSearchParams did the trick
Here is my code if it helps someone
import 'url-search-params-polyfill';
const userLogsInOptions = (username, password) => {
// const formData = new FormData();
const formData = new URLSearchParams();
formData.append('grant_type', 'password');
formData.append('client_id', 'XXXX-app');
formData.append('username', username);
formData.append('password', password);
return (
{
method: 'POST',
headers: {
// "Content-Type": "application/json; charset=utf-8",
"Content-Type": "application/x-www-form-urlencoded",
},
body: formData.toString(),
json: true,
}
);
};
const getUserUnlockToken = async (username, password) => {
const userLoginUri = `${scheme}://${host}/auth/realms/${realm}/protocol/openid-connect/token`;
const response = await fetch(
userLoginUri,
userLogsInOptions(username, password),
);
const responseJson = await response.json();
console.log('acces_token ', responseJson.access_token);
if (responseJson.error) {
console.error('error ', responseJson.error);
}
console.log('json ', responseJson);
return responseJson.access_token;
};
No need to use jQuery, querystring or manually assemble the payload. URLSearchParams is a way to go and here is one of the most concise answers with the full request example:
fetch('https://example.com/login', {
method: 'POST',
body: new URLSearchParams({
param: 'Some value',
anotherParam: 'Another value'
})
})
.then(response => {
// Do stuff with the response
});
The same technique using async / await.
const login = async () => {
const response = await fetch('https://example.com/login', {
method: 'POST',
body: new URLSearchParams({
param: 'Some value',
anotherParam: 'Another value'
})
})
// Do stuff with the response
}
Yes, you can use Axios or any other HTTP client library instead of native fetch.
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('http://identity.azurewebsites.net' + '/token', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded'
},
body: formBody
})
it is so helpful for me and works without any error
refrence : https://gist.github.com/milon87/f391e54e64e32e1626235d4dc4d16dc8
You can use FormData and URLSearchParams to post as application/x-www-form-urlencoded with the example below:
If you have a form:
<form>
<input name="username" type="text" />
<input name="password" type="password" />
<button type="submit">login</button>
</form>
You can add use the JS below to submit the form.
const form = document.querySelector("form");
form.addEventListener("submit", async () => {
const formData = new FormData(form);
try {
await fetch("https://example.com/login", {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body: new URLSearchParams(formData),
});
} catch (err) {
console.log(err);
}
});
*/ import this statement */
import qs from 'querystring'
fetch("*your url*", {
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'},
body: qs.stringify({
username: "akshita",
password: "123456",
})
}).then((response) => response.json())
.then((responseData) => {
alert(JSON.stringify(responseData))
})
After using npm i querystring --save it's work fine.
Just Use
import qs from "qs";
let data = {
'profileId': this.props.screenProps[0],
'accountId': this.props.screenProps[1],
'accessToken': this.props.screenProps[2],
'itemId': this.itemId
};
return axios.post(METHOD_WALL_GET, qs.stringify(data))
If you are using JQuery, this works too..
fetch(url, {
method: 'POST',
body: $.param(data),
headers:{
'Content-Type': 'application/x-www-form-urlencoded'
}
})
You can use UrlSearchParams and then do a toString() like so:
Here is a simple way of doing it:
fetch('https://example.com/login', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
},
body: new UrlSearchParams(...{
'userName': 'test#gmail.com',
'password': 'Password!',
'grant_type': 'password'
})
.toString()
})
.then(res => {
//Deal with response:
})
According to the spec, using encodeURIComponent won't give you a conforming query string. It states:
Control names and values are escaped. Space characters are replaced by +, and then reserved characters are escaped as described in [RFC1738], section 2.2: Non-alphanumeric characters are replaced by %HH, a percent sign and two hexadecimal digits representing the ASCII code of the character. Line breaks are represented as "CR LF" pairs (i.e., %0D%0A).
The control names/values are listed in the order they appear in the document. The name is separated from the value by = and name/value pairs are separated from each other by &.
The problem is, encodeURIComponent encodes spaces to be %20, not +.
The form-body should be coded using a variation of the encodeURIComponent methods shown in the other answers.
const formUrlEncode = str => {
return str.replace(/[^\d\w]/g, char => {
return char === " "
? "+"
: encodeURIComponent(char);
})
}
const data = {foo: "bar߃©˙∑ baz", boom: "pow"};
const dataPairs = Object.keys(data).map( key => {
const val = data[key];
return (formUrlEncode(key) + "=" + formUrlEncode(val));
}).join("&");
// dataPairs is "foo=bar%C3%9F%C6%92%C2%A9%CB%99%E2%88%91++baz&boom=pow"
Just set the body as the following
var reqBody = "username="+username+"&password="+password+"&grant_type=password";
then
fetch('url', {
method: 'POST',
headers: {
//'Authorization': 'Bearer token',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
},
body: reqBody
}).then((response) => response.json())
.then((responseData) => {
console.log(JSON.stringify(responseData));
}).catch(err=>{console.log(err)})
You can use react-native-easy-app that is easier to send http request and formulate interception request.
import { XHttp } from 'react-native-easy-app';
* Synchronous request
const params = {name:'rufeng',age:20}
const response = await XHttp().url(url).param(params).formEncoded().execute('GET');
const {success, json, message, status} = response;
* Asynchronous requests
XHttp().url(url).param(params).formEncoded().get((success, json, message, status)=>{
if (success){
this.setState({content: JSON.stringify(json)});
} else {
showToast(msg);
}
});
In the original example you have a transformRequest function which converts an object to Form Encoded data.
In the revised example you have replaced that with JSON.stringify which converts an object to JSON.
In both cases you have 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' so you are claiming to be sending Form Encoded data in both cases.
Use your Form Encoding function instead of JSON.stringify.
Re update:
In your first fetch example, you set the body to be the JSON value.
Now you have created a Form Encoded version, but instead of setting the body to be that value, you have created a new object and set the Form Encoded data as a property of that object.
Don't create that extra object. Just assign your value to body.
wrapped fetch in a simple function
async function post_www_url_encdoded(url, data) {
const body = new URLSearchParams();
for (let key in data) {
body.append(key, data[key]);
}
return await fetch(url, { method: "POST", body });
}
const response = await post_www_url_encdoded("https://example.com/login", {
"name":"ali",
"password": "1234"});
if (response.ok){ console.log("posted!"); }
For uploading Form-Encoded POST requests, I recommend using the FormData object.
Example code:
var params = {
userName: 'test#gmail.com',
password: 'Password!',
grant_type: 'password'
};
var formData = new FormData();
for (var k in params) {
formData.append(k, params[k]);
}
var request = {
method: 'POST',
headers: headers,
body: formData
};
fetch(url, request);
As I said, I want to convert that POST request with a file to JavaScript. This code sends a JSON request which contains an image file to server.
The Dart function is this (convert this to javascript):
Future postData(User user, VideoGame videoGame, File file) async {
Map data = {
'name': user.name,
'contact': user.contact,
'location': {
'country': user.country,
'state': user.state,
'city': user.city
},
'videoGame': {
'name': videoGame.name,
'type': videoGame.type,
'console': videoGame.console,
}
};
try {
String _url = baseUrl + 'insertData';
var uri = Uri.parse(_url);
var request = http.MultipartRequest('POST', uri)
..headers.addAll({'Content-type': 'multipart/form-data', 'Accept': 'multipart/form-data'})
..fields.addAll({'data': json.encode(data)});
request.files.add(
http.MultipartFile(
'image',
file.readAsBytes().asStream(),
file.lengthSync(),
filename: file.path.split("/").last
),
);
var response = await request.send();
print('Status ${response.statusCode}');
if (response.statusCode == 200) {
final respStr = await response.stream.bytesToString();
print(jsonDecode(respStr));
MyALertKey
.currentState
?.setState((){});
}
} catch (e) {
print("Video Games POST error => ${e.toString()}");
}
}
Because the server written in Python I couldn't see that this file sends to server (request full body).
I have written this in JavaScript but it doesn't work.
const handleSubmit = async (e) => {
e.preventDefault();
var data = new FormData()
var blob = new Blob([JSON.stringify({
name: somevalue,
contact: somevalue,
location: {
country: somevalue,
state: somevalue,
city: somevalue
},
videoGame: {
name: somevalue,
type: somevalue,
console: somevalue,
}
})],{
type: 'application/json'
})
data.append('data',blob)
data.append('image',file_from_input)
try {
const res = await fetch('url',{
method:'POST',
cache: 'default',
mode: 'no-cors',
headers: {
'Content-Type': 'multipart/form-data'
},
body: data
})
let data_ = await res.json()
console.log(data_)
} catch (e) {
console.log(e)
}
console.log(res.status) // will be 400 bad request
}
Please help me. Thanks.
This is the js code for post:
async function invoice() {
const baseurl = 'http://127.0.0.1:8000/api/getInvoice/';
let response = await fetch(baseurl, {
method: 'POST',
body: JSON.stringify({
userId: 1,
Total: 3333
}),
headers: {
'Content-type': 'application/json; charset=UTF-8',
},
})
.then((response) => response.json())
.then((json) => console.log(json));
}
This is the backend code:
public function getInvoice(Request $request){
$invoice = json_encode($request->all());
$result = file_put_contents(base_path('storage/app/invoice.json'),$invoice);
}
Each time while posting, it shows only one entry. i.e The content is overridden by another instead of creating new entries?
{
userId: 1,
Total: 3333
}
Try this for appending to a file instead of just overwriting it:
I've set the append flag and added a lock to the operation. Read more here.
public function getInvoice(Request $request){
$invoice = json_encode($request->all());
$result = file_put_contents(base_path('storage/app/invoice.json'), $invoice, FILE_APPEND | LOCK_EX);
}
I'm sending a post request from vue.js project using Axios and it contains a file upload, which requires me to use FormData, I found a nice answer that helped me with FormData:
const getFormData = object => Object.keys(object).reduce((formData, key) => {
formData.append(key, object[key]);
return formData;
}, new FormData());
and for the headers: headers: { 'Content-Type': 'multipart/form-data'}.
The POST call looks like this:
axios.post("http://127.0.0.1:8000/api/document/",
getFormData(this.documentData),
{
headers: {
'Content-Type': 'multipart/form-data'
}
})
.then(response => {
console.log("Successfully uploaded: ", response.data)
})
.catch(err => {
console.log("error occured: ", err)
})
This is the data I'm sending:
documentData: {
name: '',
file: '',
version: '',
company: '',
author: '',
category: []
}
When sending the data with single category id, it works fine, but when I send multiple category ids the following error shows:
"category": [
"Incorrect type. Expected pk value, received str."
]
How can I solve this problem?
Assuming your server-side process is expecting multiple, repeated field names for array types, you'll want something like this
const getFormData = object => Object.entries(object).reduce((fd, [ key, val ]) => {
if (Array.isArray(val)) {
val.forEach(v => fd.append(key, v))
} else {
fd.append(key, val)
}
return fd
}, new FormData());
Some server-side processes (PHP for example) require that collection-type fields include a [] suffix. If that's what you're working with, change this line
val.forEach(v => fd.append(`${key}[]`, v))
Also, when sending FormData from your browser, do not manually set the Content-type header. Your browser will do this for you, including the required boundary tokens
axios.post("http://127.0.0.1:8000/api/document/", getFormData(this.documentData))
.then(response => {
console.log("Successfully uploaded: ", response.data)
})
.catch(err => {
console.error("error occurred: ", err)
})
you can use json stringfy ,
I am using it also with vue app
formData.append("TeamMembers", JSON.stringify(this.TeamMembers));
axios
.post("/api/pro", formData, {
onUploadProgress: (progressEvent) => console.log(progressEvent.loaded),
headers: { "Content-Type": "multipart/form-data", }, })
Team members is an array .. and you can parse it in the other side this way
const myArr = ['bacon', 'lettuce', 'tomatoes'];
const myArrStr = JSON.stringify(myArr);
console.log(myArrStr);
// "["shark","fish","dolphin"]"
console.log(JSON.parse(myArrStr));
// ["shark","fish","dolphin"]
Object array passes values
var arr=['上海','北京'];
var formData = new FormData();
for (var i = 0; i < arr.length; i++) {
formData.append('city[]',arr[i]);
}
I'm not sure if the header or the body are configured incorrectly.
Any thoughts on whether to change the headers or maybe the body is misconfigured?
const axios = require('axios');
const url = '/my_url';
const auth = {
username: username,
password: password
};
const requestbody = {
To: 'phone',
From: 'phone 2'
};
const headers = {
'Content-Type': 'application/x-www-form-urlencoded',
}
const config = {
auth: auth,
headers: headers
}
try {
const response = await axios.post(url, {data: requestbody}, config);
console.log(response);
} catch (error) {
console.error(error);
}
Error like:
message: 'Missing required parameter To in the post body'
you need to stringify parameters and then pass directly
const querystring = require('query-string');
const query = querystring.stringify({
To: 'phone',
From: 'phone 2'
});
let options = {
headers: {
'Authorization': AUTH_HEADER,
'Content-Type': 'application/x-www-form-urlencoded'
}
};
let axios_res = await post(url, query , options);