This Meteor server code uses HTTP 1.1.7 to make a POST request to match what I did using java but I can not figure out how to include more than one entry into the request params which have the same key.
//in java 'working'
HttpParams javaParams = new HttpParams();
javaParams.add('food','milk')
javaParams.add('food', 'water')
javaParams.add('food', 'ice')
javaParams.encodeParameters("UTF-8");
//in javascript 'not working'
let headerObject {
"Content-Type" : "application/x-www-form-urlencoded",
'Accept-Language': 'en-US,en;q=0.5'
and others
}
const response = HTTP.call('POST', myUrl, {
timeout: 30000,
headers: headerObject,
params: {
'food': 'milk',
'food': 'water',
'food': 'ice'
}
});
//also tried these but server returned status code 500
food: ['milk', 'water', 'ice']
'food[]': ['milk', 'water', 'ice']
How can it this be done? Thanks
In JavaScript, just use an array:
const response = HTTP.call('POST', myUrl, {
timeout: 30000,
headers: headerObject,
params: {
food: ['milk', 'water', 'ice']
}
});
However, different languages on the server side use different mechanisms to handle parameter arrays. While Java should work with the above code, PHP for example needs the parameter name to contain square brackets, so the call would need to be
const response = HTTP.call('POST', myUrl, {
timeout: 30000,
headers: headerObject,
params: {
'food[]': ['milk', 'water', 'ice']
}
});
In the current case, the server side seems to expect each entry in a separate line of the request content as key=value pairs which each key being 'food'. Regrettably, this cannot be done with an JavaScript array nor with a JavaScript object.
To circumvent this problem, we use data instead of params. This prevents HTTP.call() from creating data from the given params. It only requires us to handle concatenation of the parameters ourself:
const response = HTTP.call('POST', myUrl, {
timeout: 30000,
headers: headerObject,
data: "food=milk\nfood=water\nfood=ice"
});
Related
I have attempted to create a request in javascript, that has previously worked using python just fine.
the following is an accurate representation of the code I used to post the request with python:
url = 'https://website.com/api/e1'
header = {
'authorization': 'abcd1234'
}
payload = {
'content': "text",
}
r = requests.post(url, data=payload,headers=header )
This (above) works just fine in python.
now what I did in javascript is the following:
payload = {
"content": "this is text",
};
fetch("https://website.com/api/e1", {
method: "POST",
headers: {
"authorization":
"abcd1234",
},
body: JSON.stringify(payload),
});
but this is returning the error
400- Bad request
When using data parameters on python requests.post, the default Content-Type is application/x-www-form-urlencoded(I couldn't find it on the document, but I checked the request. If you know, please leave a comment).
To achieve the same result with fetch, you must do as follows.
const payload = {
'content': 'this is text',
};
fetch('https://website.com/api/e1', {
method: 'POST',
headers: {
'authorization': 'abcd1234',
},
body: new URLSearchParams(payload),
});
You don't need to do this body: JSON.stringify(payload), rather you can simply pass payload in body like this body:payload
I have tried many different ways but to no avail
API Spec - https://developers.facebook.com/docs/graph-api/reference/page/videos/
Param - content_tags ( list ) --> is what required
Below is my form data that is being posted
const formData = {
file_url: postOptions.filepath,
title: postOptions.title,
description: postOptions.description,
content_tags: ['tags', 'hello', 'hi']
};
HTTP Request Options
const options = {
url: https://graph-video.facebook.com/v9.0/${pageId}/videos?access_token=${accessToken},
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data',
'Cache-Control': 'no-cache',
Connection: 'keep-alive',
},
formData,
};
Error response returned.
{"error":
{
"message":"(#100) Param content_tags[0] must be a valid ID string (e.g., \"123\")",
"type":"OAuthException",
"code":100,
"fbtrace_id":"ANoCbTSnh4uL960SjyE6XBV"
}
}
As per documentation, seems it has to be not just any string but NUMBER string which are predefined IDs of the tag list<numeric string>
From documentation
Tags that describe the contents of the video. Use search endpoint with type=adinterest to get possible IDs.
Example:
~~~~
/search?type=adinterest&q=couscous
~~~~
Here's full path of the above example shown by facebook, how you can get some IDs:
https://graph.facebook.com/search?type=adinterest&q="home"&limit =10&access_token={{access_token}}
Given a simple fetch request i.e.
fetch('https://api.com/endpoint', {
method: "POST"
});
Is it possible / how can following object be converted to query params / query string to append to the fetch request? Most methods online recommend using new URLSearchParams helper, however it doesn't seem to work with nested objects and when converted to string these nested objects are returned as [Object object] string. Ideal solution should not rely on any third party packages.
{
side: 'buy',
symbol: 'AAPL',
type: 'market',
qty: '2',
time_in_force: 'gtc',
order_class: 'bracket',
take_profit: {
limit_price: '200'
},
stop_loss: {
stop_price: '200'
}
}
Form your fetch request like this:
fetch('https://api.com/endpoint', {
method: "POST",
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(dataYouWannaPost)
});
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.
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}`
})