Post nested objects in query string - Node.js - javascript

My code is attempting to post data to a Coldfusion API from my local Node.js server. I have managed to communicate with the API and authenticate myself via the request headers. However I am having difficulty actually passing my JSON object through as I cannot get the structure right.
The API does not accept the JSON option of the request module, so that is my easiest option out of the window.
The API is expecting the following:
{
'source': {
'customer': {
'customerlogin': 'myusername',
'customerpassword': 'mypassword',
}
}
}
my code works if I hard code the following body parameter (from a sucessful post by somebody else) into my post.
var Jrequest = require('request');
var options = {
uri: 'http://myAPI/customerSSO.json',
headers: {'Content-Type': 'application/x-www-form-urlencoded', 'Authorization': something', 'Timestamp': timestamp},
method: 'POST',
body: 'source=%7B%0D%0A++%22customer%22%3A+%7B%0D%0A++++%22customerlogin%22%3A+%22myusername%22%2C%0D%0A++++%22customerpassword%22%3A+%22mypassword%22%2C%0D%0A%09%22success%22%3A+%22%22%0D%0A++%7D%0D%0A%7D' // Working
};
Jrequest(options, function (error, response, body){
res.send(body);
});
If I send the JSON through in other ways, for example json.stringify(), it is rejected on the grounds that 'source is required but not defined'.
So I suppose my question is, in node.js how do I turn JSON into something that looks like this
'source=%7B%0D%0A++%22customer%22%3A+%7B%0D%0A++++%22customerlogin%22%3A+%22myusername%22%2C%0D%0A++++%22customerpassword%22%3A+%22mypassword%22%2C%0D%0A%09%22success%22%3A+%22%22%0D%0A++%7D%0D%0A%7D'
or have I overlooked another option?
Thanks for any help and apologies if I have used incorrect terminology.

I think this should work:
var querystring = require('querystring');
...
request({
...
headers : { 'Content-Type': 'application/x-www-form-urlencoded', ... },
body : 'source=' + querystring.escape(JSON.stringify({
'customer': {
'customerlogin': 'myusername',
'customerpassword': 'mypassword',
}
})),
...
}, ...)
Your example also contains newlines and carriage returns and such, but I'm assuming those are optional.

Related

Postman POST works, but not with axis

Making a post request via insomnia/postman works, gives me the correct response. However, in axios, I can't seem to make it work.
It doesn't give me an error, its a status 200, but doesn't actually login like postman/insomnia does. I feel something is wrong with my axios setup
const { email, password } = req.body.params
const endpoint = `https://xxxxxxxxx.com/account/login/`
try {
const response = await axios({
method: 'post',
url: endpoint,
data: qs.stringify({
'customer[email]': email,
'customer[password]': password,
'form_type': 'customer_login'
}),
headers: {
'content-type': 'application/x-www-form-urlencoded'
}
})
res.status(200).send(response.data)
} catch (error) {
res.status(500).send(error)
}
There are 2 solutions (I hope) :
1/ Following this post, you should probably use withCredentials like this :
const { email, password } = req.body.params
const endpoint = `https://xxxxxxxxx.com/account/login/`
axios.defaults.withCredentials = true;
try {
(...)
}
2/ Following this article, you need to set your Content-Type header to application/json so the data is automatically parsed :
Axios also sets the Content-Type header to application/json. This enables web frameworks to automatically parse the data.
Postman lets you generate the code necessary to recreate your request using axios.
More information on that here: https://learning.postman.com/docs/sending-requests/generate-code-snippets/
Click the code icon to the right of Postman
Then set the code snippet language to NodeJS - Axios and you'll have the exact code necessary to recreate the request.

How to use the RapidAPI in Excel VBA

I'm new to using RapidAPI. I want to pull live Cricket Scores from RapidAPI with Excel VBA, but the programming language isn't available on the platform.
I would like to know if there is anyway I can view the json results directly through a browser. This is what I read in their documentation https://docs.rapidapi.com/docs/getting-started-with-rapidapi-sdks but doesn't seem to solve my problem
"What If the Programming Language I'm Using Isn't Available?
Whether the programming language you're using isn't available or you prefer to use another request library, have no fear! All of the APIs available on RapidAPI are exposed through a REST API endpoint. All you'll need to do is take the information provided on the documentation provided. Here's an example of what that would look like using the 'request' npm module"
var options = {
method: 'POST',
url: API_URL,
headers: {
'cache-control': 'no-cache',
'Content-Type': 'application/json',
'X-RapidAPI-Key': API_KEY,
'header1': 'header-value-1'
},
qs: {
parameter1: 'parameter-value-1'
}
};
request(options, function (error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
I'm looking for a better idea of working with RapidAPI in Excel VBA. If I can get the json response directly in a browser that solves my problem. But if that's not possible, any example to setup a Node.JS server offline and possibly display the json response in a browser may also work. Thanks in advance
Const Covid19URL As String = "https://covid-193.p.rapidapi.com/history?day=2020-03-25&country=Malaysia"
Const APIKey As String = "brx2HKOJvP6iQ14WxeumLmnhx2L2MAZz"
Sub Main()
Dim xmlhttp As New MSXML2.XMLHTTP60
Dim xmlresponse As New DOMDocument60
xmlhttp.Open "GET", Covid19URL, False
xmlhttp.setRequestHeader "x-rapidapi-host", "covid-193.p.rapidapi.com"
xmlhttp.setRequestHeader "x-rapidapi-key", APIKey
xmlhttp.send
Cells(2, 12).Value = xmlhttp.responseText
'xmlresponse.LoadXML (xmlhttp.responseText)
'"response":[
'{"country":"Malaysia","cases":{"new":"+172","active":1596,"critical":64,"recovered":183,"total":1796},"deaths":{"new":"+1","total":17},"day":"2020-03-25","time":"2020-03-25T09:15:07+00:00"},
'{"country":"Malaysia","cases":{"new":"+172","active":1597,"critical":64,"recovered":183,"total":1796},"deaths":{"new":null,"total":16},"day":"2020-03-25","time":"2020-03-25T07:15:06+00:00"},
'{"country":"Malaysia","cases":{"new":"+106","active":1425,"critical":64,"recovered":183,"total":1624},"deaths":{"new":"+2","total":16},"day":"2020-03-25","time":"2020-03-25T06:15:05+00:00"}
Set xmlresponse = Nothing
Set xmlhttp = Nothing
End Sub

Using a oauth token in second request - NODEJS

Thanks for your help in advance.
I am trying to solve a problem that has bugged me pretty much for a few weeks now on and off (tried to solve it myself) and i am pretty stuck.
Basically i have a scenario where i am sending a data call to a identity server (Oauth 2.0) to retrieve a token that is then used in a API call.
To do this, i have setup two calls to the request module in NodeJS. The first call queries the server whilst the second call needs to use the token retrieved in the first to access the API i am accessing.
I cannot figure out how to get the variable from the first call (the token) to be accessible to the second request. I keep getting that it is undefined from the console.
This is the code i have tried so far. Relevant variable. Trying to take variable token through to request 2 as i need that token for the api call. I am running these requests in a function called dostuff.
var request = require('request');
var http = require('http');
var fs = require('fs');
var options = {
url: 'https://identitywebsite.com/connect/token',
headers: {'authorization' : 'basic <<KEY>>', 'Content-Type' : 'application/x-www-form-urlencoded'},
port: '443',
path: '/users',
method: 'POST',
body: 'grant_type=password&username=<<USERNAME>>&password=<<PASSWORD>>&scope=read+write'
var dostuff = function() {
request(options, function(error, response, body){
console.log("success");
Data = JSON.parse(body);
//console.log(xx);
global.token = data.access_token;
})
};
var options2 = {
url: 'https://apiwebsite.com',
headers: {'authorization' : 'Bearer ' + token, 'Content-Type' : 'application/json'},
port: '443',
path: '/users',
method: 'GET'
}
console.log(options2);
request(options2, function(error, response, apiresponse){
console.log("triggered");
console.log(" data success2");
apidata = JSON.parse(apiresponse);
console.log(apidata);
});
Well a few things you should do. One is use some promises. Also do your best to not use global variables.
Also you are missing a closing bracket on your first options.
Promises are really neat though, as you can do things like this.
do_something(options)
.then(function(my_data){
var options2 = {
url: 'https://apiwebsite.com',
headers: {'authorization' : 'Bearer ' + my_data, 'Content-Type' : 'application/json'},
port: '443',
path: '/users',
method: 'GET'
}
do_something_else(options2)
.then(function(my_other_data){
//do stuff with my_other_data
}
}
Use this library! It makes doing promises with requests really easy!
https://github.com/request/request-promise, you could also do this in bluebird which is my favorite of all the promise libraries, but it is slightly more complex.
Edit:
Since someone posted that this is off topic, which it isn't. I will go farther in depth of why this is not working the way you think it should. One of the reasons this is not working quite right is Node.JS is asynchronous.
What this means is your code is not waiting for your first request to finish before running your second request so you are not actually getting the token before your next request needs this.
One of the ways around this is to use promises like I said originally. There are plenty of libraries out there that force synchronicity. There is this library for example:
https://github.com/yortus/asyncawait
and many many more.
You could abstract this farther and call your first request from your second request as well to grab the API key and store it.

Send Array in post request using node.js using application/x-www-form-urlencoded

I tried to send post request to API and the post parameters should be array,
this is how to send it in cURL
curl http://localhost:3000/check_amounts
-d amounts[]=15 \
-d amounts[]=30
I tried to do that in Node.js using request module
request.post('http://localhost:3000/check_amounts', {
form: {
'amounts[]': 15 ,
'amounts[]': 30
}
}, function(error, response, body) {
console.log(body)
res.json(body);
});
but the second amount override the first one and the API gets the result as following: amounts = [30]
Then I tried to send it in different way
request.post('http://localhost:3000/check_amounts', {
form: {
'amounts[]': [ 15 , 30]
}
}, function(error, response, body) {
console.log(body)
res.json(body);
});
but the result was not as an expected amounts = [{"0":15},{"1":30}]
Note : the header should contains 'Content-Type': 'application/x-www-form-urlencoded' not 'application/json'
Does any one have solution to this problem?
It's quite easy if you read the manual of request. All you should do is replace the form by querystring rather than object, in your case this should be:
amounts=15&amounts=30
the only thing I'm not sure is the above expression works in your web server. As I know it works well in java struts. So if not you may try
amounts[]=15&amounts[]=30 instead. Hope it help.

Data is not passed from AngularJS controller to NodeJS server

I am attempting to pass some values from my client-side AngularJS script to a server-side NodeJS script. I set up the POST request like so:
$scope.addUser = function() {
console.log($.param($scope.user));
$http({
method: 'POST',
url: '/addUser',
data: $.param($scope.user),
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
}).
success( function(response) {
console.log("success");
}).
error( function(response) {
console.log("error");
});
};
The $scope.user variable is { name: "john", email: "doe" }, and evaluates to name=john&email=doe when passed through $.param($scope.user). I originally thought the problem was the content-type of the request, which was originally a JSON object. After reading about similar problems I changed the content-type to x-www-form-urlencoded, but still could not grab the data from the POST request.
Here is the server-side NodeJS script that is hit with the POST request:
app.post('/addUser', function(req, res) {
console.log(req.params);
});
I know the server-side script is being reached, as I can print out data such as req.method, but attempting to print req.params results in just { }.
Why are my POST parameters not going through?
Request bodies are not saved to req.params. You need to add a middleware to parse the request body for you. req.params is for key=value pairs supplied as part of the URL (e.g. POSTing to "/foo/bar?baz=bla" would result in req.params.baz === 'bla').
Some example solutions:
body-parser - parses only application/json and application/x-www-form-urlencoded request bodies.
formidable - parses application/json, application/x-www-form-urlencoded, and multipart/form-data. This is what was used in the body parser in Express 3. I'm not sure if there is an "official" Express middleware for it for Express 4.
busboy - parses application/x-www-form-urlencoded and multipart/form-data. It does not save files to disk itself, but instead presents files as readable streams. The API differs from formidable(/body parser from Express 3). There are a few Express middleware available for busboy:
connect-busboy - a thin wrapper that merely sets up a Busboy instance on your req. You can set it to automatically start parsing the request, or you can pipe the request manually to req.busboy when you want to start.
multer - provides an interface more similar to the Express 3 body parser middleware (with req.body and req.files set).
reformed - a new module that provides a layer on top of Busboy to provide mechanisms similar to formidable (e.g. saving uploaded files to disk) but also other features such as field validation.
Since you are using express.js your POST fields are received as part of the body not the URL so you need use body instead of params:
app.post('/addUser', function(req, res) {
console.log(req.body);//also possible req.body.name | req.body.email
});
How about trying a simpler POST something like this (for testing purposes only):
$http.post('/addUser',{ "name": "john", "email": "doe" }).success(function(response) {
console.log("success");
}).error(function(err){
console.log("failure")
});
Please note that Params are used as URL parameters; something like this:
app.get('/addUser/:userID', function(req, res) {
console.log(req.params.userID);
});

Categories