Send nested json data with get method using axios - javascript

I am trying to send a nested json data with get method using axios, but the problem is that the backend considers the children as a string.
const TOKEN = "token"
const config = {
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': TOKEN,
},
data: {},
params: {
"page_id": 1,
"filter": {
"search": "name"
}
}
};
axios.get("http://localhost/api/pages", config)
What I get if I want to print filter in backend:
"{"search": "name"}"

You may have two options:
1- The first option is to decode the string you receive to json.
e.g.
---json_decode() in php
--- JSONObject() in java
--- JSON.parse() in nodejs
or any other method depending on your backend language...
2- The second option is to send your object in this format:
params: {
"page_id": 1,
"filter[search]": "name"
}
And pay attention not to put search in quotes!

You can use req.query on the server side:
function get(req, res, next) {
const { filter } = req.query;
console.log(filter);
...
}

Do a JSON.parse() of your Request.query.filter. Note that Request should be the request variable in your backend.

Related

set Content-Type to application/Json using Fetch API javascript

I am trying to send some form data to a spring application using Fetch API in javascript.
I have this code to send the form data:
document.querySelector('#formPet').addEventListener('submit', event => {
event.preventDefault();
let email= document.querySelector("#email");
fetch('http://localhost:8080/petForm/'+email.value+'/pets', {
method: 'POST',
body: JSON.stringify({
help: "helpme:("
})
})
});
but i get a 415 status error "Unsupported Media Type". Even when i set specifically the header 'Content-Type' to 'application/json' it sends like 'text/plain'
fetch('http://localhost:8080/petForm/'+email.value+'/pets', {
method: 'POST',
header: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
help: "helpme:("
})
})
});
this is the response that i get from the server:
Here is the method that accept the request in Spring:
#PostMapping("petForm/{id}/pets")
public ResponseEntity<Pet> createPet(#PathVariable("id") String ownerId, #RequestBody Map<String, Object> data){
System.out.println(data);
return ResponseEntity.ok().build();
}
i don´t know why the request is send in 'text/plain' format, i try the Spring method in postman and work´s fine when i send the data in json format.
In your JavaScript code you need to use „headers“ instead of „header“. See the fetch API documentation: https://developer.mozilla.org/en-US/docs/Web/API/fetch
step 1 : add #CrossOrigin after #PostMapping(value = "petForm/{id}/pets")
like :
#PostMapping(value = "petForm/{id}/pets")
#CrossOrigin
public ResponseEntity<String> createPet(#PathVariable("id") String ownerId, #RequestBody Map<String, Object> data){
System.out.println(data);
return ResponseEntity.ok().build();
}
step 2 : add double quotes to help word
it is not json fromat :====> help: "helpme"
Correct :
it is not json fromat :====> "help": "helpme"

Errors while trying to "Put" JSON Data

I am working with the Hubspot API and I am trying to modify the close date of a deal via the "PUT" Method by sending JSON Data. But I am getting errors such as
{ status: 'error', message: 'Invalid input JSON on line 1, column
15: Can not deserialize instance of java.util.ArrayList out of
START_OBJECT token', correlationId:
'b8b47229-184d-40b3-b402-9e3dd684b217', requestId:
'd364fe8dac5e876639928dd0d04045fd' }
This is the code that I have written-
fetch('https://api.hubapi.com/deals/v1/deal/103361780?hapikey=', {
method: 'put',
headers: {
'Accept': 'application/json, text/plain, */*',
'Content-Type': 'application/json'
},
body: JSON.stringify({"properties":{name: "closedate", "value": 1528744207881}})
}).then(res=>res.json())
.then(res => console.log(res));
This is the JSON Data that I am trying to pass
{
"properties":[
{
"name": "closedate",
"value": 1528744207881
}
]
};
And here is the documentation of making a PUT request via the Hubspot API.
I am able to successfully update the value via POSTMAN.
Any help on this matter would be greatly appreciated.
You are missing brackets - [] and on the backend, they are waiting for an array to deserialize it to Arraylist.
Try fetch with this body:
{"properties":[{"name": "closedate", "value": 1528744207881}]}

Axios posting params not read by $_POST

So I have this code:
axios({
method: 'post',
url,
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
data: {
json,
type,
}
})
Originally I had the normal axios.post but I changed to this because I thought it might have been a header problem. However I am still detecting nothing in my $_REQUEST nor $_POST. However, it is receiving data in file_get_contents("php://input").
Any idea what is wrong?
Edit
Okay I think I know what's wrong. It's posting it as a json object so it can only be read in the php://input. How do I change it to a normal string in axios?
From the documentation (I haven't preserved links in the quoted material):
Using application/x-www-form-urlencoded format
By default, axios serializes JavaScript objects to JSON.
PHP doesn't support JSON as a data format for populating $_POST.
It only supports the machine-processable formats natively supported by HTML forms:
application/x-www-form-urlencoded
multipart/form-data
To send data in the application/x-www-form-urlencoded format instead, you can use
one of the following options.
Browser
In a browser, you can use the URLSearchParams API as follows:
var params = new URLSearchParams();
params.append('param1', 'value1');
params.append('param2', 'value2');
axios.post('/foo', params);
Note that URLSearchParams is not supported by all browsers, but there
is a polyfill available (make sure to polyfill the global
environment).
Alternatively, you can encode data using the qs library:
var qs = require('qs');
axios.post('/foo', qs.stringify({ 'bar': 123 }));
Or you could customise your PHP so it can handle JSON as per this answer on another question.
var params = {
data1: 'string',
}
axios.post(url, params).then(function(response) {
//code here
});
or
axios.post(url, {data1: 'string' }).then(function(response) {
//code here
});
api
$_POST = json_decode(file_get_contents("php://input"),true);
echo $_POST['data1'];
To make things easier and universal if you ever decided to switch between AJAX libraries or server languages. With axios use the native JS FormData.
If you have your data in an object, you can convert it to FormData like this:
var myDataObj = {id:1, name:"blah blah"}
var formData = new FormData();
for (var key in myDataObj) {
formData.append(key, myDataObj[key])
}
Then you send the data:
axios.post('/sub/process.php', formData, {
params: { action: "update-user" },
headers: { 'Content-Type': 'multipart/form-data' },
baseURL: 'http://localhost',
}).then(data =>
console.log(data)
).catch(err => {
console.log(err)
return null
})
Notice, you can also send some info using params in axios that you can retrieve using $_GET. Also notice that I am using the baseURL in case you have different servers for the web page and your API endpoint.
You need to understand also that before axios send the real request, it performs a preflight request. A preflight request, is a mechanism in CORS by the browser to check if the resource destination is willing to accept the real request or not. Afterall, why would a request be sent when the target host is not willing to receive it anyway?
You have to make sure that your server has the right headers for your axios request, otherwise the preflight request will detect the incompatibility and stop your request:
//this is if you are using different different origins/servers in your localhost, * to be update with the right address when it comes to production
header('Access-Control-Allow-Origin: *');
//this is if you are specifying content-type in your axios request
header("Access-Control-Allow-Headers: Content-Type");
Now, you will able to access your sent data in the $_POST variable:
echo "<pre>";
print_r($_POST);
echo "</pre>";
Additionally, axios allows you to send data in different formats. you can send a json for example like this:
axios.post('/sub/process.php', { id: "1", name:"blablah" }, {
params: { action: "update-item" },
headers: { 'Content-Type': 'application/json' },
baseURL: 'http://localhost',
}).then(data =>
console.log(data)
).catch(err => {
console.log(err)
return null
})
In the PHP side, this can be accessed as follows:
$data = json_decode(file_get_contents("php://input"),true);
echo "<pre>";
print_r($data);
echo "</pre>";
Using PHP std object
Using PHP std object structure to get the variables of the post.
On the client:
axios.post(url, {id: 1 , Name:'My Name' }).then(function(response) {
console.log(response.data);
});
On the server
$obj = json_decode(file_get_contents('php://input'));
$id = $obj->id;
$Name = $obj->Name;
//test by returning the same values
$retObj=(object)["id"=>$id,"Name"=>$Name]
echo json_encode($retObj);
Both jQuery and Axios using same PHP file
if you have a file receiving post both from axios and jquery you may use:
if($_SERVER['REQUEST_METHOD']==='POST' && empty($_POST)) {
$_POST = json_decode(file_get_contents('php://input'),true);
}
to convert the Axios json-serialized posts to the $_POST array
This code works on browser/node both today.
I think this is more practical.
I tested this code on node.js and passed the data variable to PHP8 using $_POST['param1'] and it worked perfectly.
function axqs(d){
let p = new URLSearchParams();
Object.keys(d).forEach(function(key){
p.append(key, this[key]);
}, d);
return p
}
let data = {
'param1': 'value1',
'param2': 'value2',
}
let p = axqs(data)
axios.post('/foo', p)
Just wanted to share my insights, I was facing a similar problem and solved it by the following code set
JS
const instructions_str = {
login: {
"type": "devTool",
"method": "devTool_login",
"data": {
"username": "test",
"password": "Test#the9"
}
},
tables: {
"type": "devTool",
"method": "devTool_get_all_tables",
"data": ""
}
};
const body = {
firstName: 'Fred',
lastName: 'Flintstone',
name: "John",
time: "2pm",
instructions : JSON.stringify(instructions_str)
};
function decodeData(data) {
const serializedData = []
for (const k in data) {
if (data[k]) {
serializedData.push(`${k}=${encodeURIComponent(data[k])}`)
}
}
return serializedData.join('&')
};
const body2 = decodeData(body);
axios.post('URL', body2)
.then(response => {
console.log("contextApi got it", response);
}).catch(error => {
console.log("contextApi error.response", error.response);
});
PHP
// set content return type
header('Content-Type: application/json');
// Setting up some server access controls to allow people to get information
header("Access-Control-Allow-Origin: *");
header('Access-Control-Allow-Methods: POST, GET');
// This way I can check and see what I sent
$postVars_array = $_POST ?? parse_str(file_get_contents("php://input"),$postVars_array) ?? [];
echo json_encode($postVars_array);
I also found this github page very helpful https://github.com/axios/axios/issues/1195

How to add data to request body while proxying it

I have a call made from my client that passes in some post data like this:
function doSomethingApi(email) {
return axios({
method: 'post',
url: `/api`,
data: {
scan_refference: 'ref',
user_email: email
}
})
}
On the server side this gets proxied to apply certain secrets:
app.post('/api', (req, res) => {
const url = 'https://my.api.com';
req.pipe(request({
url,
headers: {
'Content-Type': 'application/json',
Accept: 'application/json'
},
auth: {
user: secrets.USERNAME,
pass: secrets.PASSWORD
},
body: {
value1: `${secrets.VALUE1}`,
value2: `${secrets.VALUE2}`
}
})).pipe(res);
});
request and axios are just 2 different http libraries I use, one is preferred for client other for server, thats all. Issue now is that I am overwriting body in my proxy, where as I want to simply add value1 and value2 to existing body passed from client.
First get the body from the initial call as a JSON object. This depends on what you use, but e.g. in Express you could:
app.use(express.bodyParser());
Then
var previousBody = req.body
Finally merge the initial JSON with whatever you want (NOTE: this means your client will definitely not be able to use the "value1" and "value2" properties, because they will be overwritten)
body: Object.assign(previousBody, {
value1: `${secrets.VALUE1}`,
value2: `${secrets.VALUE2}`
})

HTTPS request not posting body of REST request

I'm trying to POST to an API endpoint on my server. I know my endpoint works because if I use Advanced REST Client, I can hit it and get a JSON response as expected. The problem seems to be that no data is being sent in the body of my request despite calling request.write(postData) which contains a key, value pair. Without this data being sent in the body, my server returns a 401 error as expected without this information. Printing out the content of the POST server-side is empty but I'm clueless as to why it's empty.
var postData = querystring.stringify({
"access_token" : accessToken,
"id": applianceId
});
var serverError = function (e) {
log("Error", e.message);
context.fail(generateControlError(requestName, "DEPENDENT_SERVICE_UNAVAILABLE", "Unable to connect to server"));
};
var callback = function(response) {
var str = "";
response.on("data", function(chunk) {
str += chunk.toString("utf-8");
});
response.on("end", function() {
result = generateResult(CONTROL, requestName.replace("Request", "Confirmation"), messageId);
context.succeed(result);
});
response.on("error", serverError);
};
var options = {
hostname: REMOTE_CLOUD_HOSTNAME,
port: 443,
path: REMOTE_CLOUD_BASE_PATH + "/" + endpoint,
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded"
}
};
var request = https.request(options, callback);
request.on("error", serverError);
//This doesn't seem to write anything since if I print out the POST
//data server-side it's empty; however, if I print out the value of
//postData here, it looks as expected: 'access_token=xxxxx'
request.write(postData);
request.end();
I have testing you code again httpbin.org/post and it seems that it is working.
I believe that the issue related to, that your should POST application/json and not "application/x-www-form-urlencoded
Please try to change the header
headers: {
"Content-Type": "application/json"
}
Then, try to change the postData to JSON string:
var postData=JSON.stringify({access_token:"xxxxx"})
To be sure that problem you success to send and the problem is not local (maybe there is an issue in your server), change the target to mirror URL:
var options = {
hostname: "httpbin.org",
path:'/post',
port: 443,
method: "POST",
headers: {
"Content-Type": "application/json"
}
};
If there is no problem in your NodeJS version, the is the response you should get: (It is mean that the server got the posted data)
{
"args": {},
"data": "{\"access_token\":\"xxxxx\"}",
"files": {},
"form": {},
"headers": {
"Content-Length": "24",
"Content-Type": "application/json",
"Host": "httpbin.org"
},
"json": {
"access_token": "xxxxx"
},
"origin": "5.29.63.30",
"url": "https://httpbin.org/post"
}
BTW: I really recommend you to move to a library to manage the request for you:
https://github.com/request/request - Very popular
https://github.com/request/request-promise - For popular who like to use the Promise syntax (The next thing in JavaScript)
https://github.com/visionmedia/superagent - For people who like to write same code in Browser & Server

Categories