Post call from Nodejs - node.js

I am trying to get an authentication token from an API.
the request is supposed to look like
POST /oauth2/token HTTP/1.1
Host: mysageone.ca.sageone.com
client_id=4b64axxxxxxxxxx00710&
client_secret=iNumzTxxxxxxxxxxhVHstrqWesH8tm9&
code=12a0f9c12cxxxxxxxxxxxxxxx92a48cc1f237ead&
grant_type=authorization_code&
redirect_uri=https://myapp.com/auth/callback
My current code keeps giving me status 400. I have tried to modify the headers but it doesn't work. i have also tried to make the required parameters part of the path using ?.
const http = require('http');
var options = {
hostname: 'app.sageone.com',
path: '/oauth2/token',
method: 'POST',
headers: {
"client_id":"xxxxx",
"client_secret":"xxxxx",
"code":"xxxxxx",
"grant_type":"authorization_code",
"redirect_uri":"https://some link"
}
};
console.log('in users file point 2');
var req1 = http.request(options, (res1) => {
console.log('statusCode:', res1.statusCode);
console.log('headers:', res1.headers);
console.log('message',res1.statusMessage);
res1.on('data', (d) => {
res.json(d);
});
});
req1.on('error', (e) => {
console.error('error starts here',e);
});
req1.end();
});

Looks to me like your problem is not with Node.js, but with your use of Sage One's api. This is the relevant documentation that might solve your problem.
From a quick glance it looks like you want to send a GET not a POST, and you should send those parameters in the URL. Here is the example URL they give:
https://www.sageone.com/oauth2/auth?response_type=code&client_id=4b64axxxxxxxxxx00710&redirect_uri=https://myapp.com/auth/callback


&scope=full_access
I've never used Sage One before, but that would match my experience with other OAuth APIs.

Related

How to make HTTP request to Discord API?

I am trying to make an HTTP request to the Discord API, and I keep getting ECONNREFUSED as an error back. I am trying to access this route provided in the Discord API Documentation:
Get Global Application Commands GET/applications/{application.id}/commands
Fetch all of the global commands for your application. Returns an array of ApplicationCommand objects.
Using NodeJS, here is the relevant section of code:
const https = require('https')
const options = {
hostname: 'https://discord.com',
path: '/api/v8/applications/<myapplicationID>/commands', //with my actual appID
port: 443,
method: 'GET',
headers: {
Authorization: `Bot ${process.env.TOKEN}`
}
}
const req = https.request(options, res => {
console.log(`statusCode: ${res.statusCode}`)
res.on('data', d => {
process.stdout.write(d)
})
})
req.on('error', error => {
console.error(error)
})
req.end()
I know this is a relatively simple question, but looking at the related questions didn't provide much insight, and as far as I can tell, I am adhering to the API's documentation. Any advice would be very helpful.
Thanks,
Dylan
So it was pretty stupid... The hostname field can't have 'https://'

How to make an https version of a Unirest example

I would like to use the https library in node.js to send a request to this api:
https://rapidapi.com/dimas/api/NasaAPI?endpoint=apiendpoint_b4e69440-f966-11e7-809f-87f99bda0814getPictureOfTheDay
The given example on the RapidAPI website uses Unirest, and I would like to only use the https library. I've tried to write it like this:
const https = require('https');
var link = "https://NasaAPIdimasV1.p.rapidapi.com/getPictureOfTheDay";
var options = {host: "https://NasaAPIdimasV1.p.rapidapi.com/getPictureOfTheDay",
path: "/", headers: {"X-RapidAPI-Key": "---MY KEY(Yes, I've replaced it)---", "Content-Type": "application/x-www-form-urlencoded"}}
https.get(link, options, (resp) => {
let data = '';
resp.on('data', (chunk) => {
data += chunk;
});
resp.on('end', () => {
console.log(data);
});
}).on("error", (err) => {
console.log("https error 4: " + err.message);
});
But that returns the following response:
{"message":"Endpoint\/ does not exist"}
Thanks for any help
There are several mistakes.
First, you essentially pass URL in https twice - first as link param, second as combination of host and path properties for options param.
Second, your host is actually the full path - but it shouldn't be. In the end, looks like the library got confused and sent request to https://NasaAPIdimasV1.p.rapidapi.com/ instead.
Finally, this particular API requires using 'POST', not 'GET' method. That's actually mentioned in the documentation. That's why you have 'endpoint does not exist' error even on correctly formed request.
One possible approach is dropping link altogether, sending URL as part of options:
var options = {
host: 'NasaAPIdimasV1.p.rapidapi.com',
method: 'POST',
path: '/getPictureOfTheDay',
headers: {/* the same */}
};
https.request(options, (resp) => { /* the same */ }).end();

Express JS - Network connection was lost

I am trying to set up an express js server that will be hosting a mongodb database. Everything is pretty standard: I have some routes open that will take in data from the client and then store that in the database.
Here is my query string:
let url = "http://xxx.xxx.xx.xxx:3000/update/data=" + JSON.stringify(params);
What I have noticed is that if params doesn't contain much information, it works fine. However, if params is contains a lot of information, then the client throws this error:
Failed to load resource: The network connection was lost.
Http failure response for (unknown url): 0 Unknown Error
(This same error is happening in both Safari and Chrome.)
For example, if params is as below:
{
"accountId": "12345678910",
"data": [
1, 2, 3, 4
]
}
then there is no issue. However, if params.data is a huge array with a ton of information in it instead of just [1, 2, 3, 4], then the error is thrown.
Also, my express server never even seems to receive the request. No logs; nothing. What I would expect to happen is just a normal response and result, however it seems like the client is just giving up on sending something large. Perhaps it has something to do with sending it as a big string?
You put your data on your URL. But, URLs have limited length.
You need to use POST and put your data in the HTTP request body.
You haven't shown us how you use that URL, so it's hard to make suggestions about altering your code. Using the http request operation is the way to go. Something like this might work...
const payload = JSON.stringify(params);
const url = 'http://xxx.xxx.xx.xxx:3000/update/';
const options = {
method: 'POST', // <--- tell it to POST
headers: {
'Content-Type': 'application/json', // <--- tell it you're posting JSON
'Content-Length': payload.length; // <--- tell it how much data you're posting.
}
};
const req = http.request(url, options, (res) => {
/* handle stuff coming back from request here */
console.log(`STATUS: ${res.statusCode}`);
console.log(`HEADERS: ${JSON.stringify(res.headers)}`);
res.setEncoding('utf8');
let chunks=[];
res.on('data', (chunk) => {
chunks.push(chunk);
console.log(`BODY: ${chunk}`);
});
res.on('end', () => {
const resultingData = chunks.join();
console.log('No more data in response.');
});
});
req.on('error', (e) => {
console.error(`problem with request: ${e.message}`);
});
// write data to request body
req.write(payload);
req.end();

IIS authentication for http request with Nodejs

I have one problem with HTTP GET/POST request.
When I use the DHC/Postman, send the parameters to the URL + endpoint, works perfectly. 200 is returned.
But with code, like my example, show one 401 error.
I have searched about that and the problem is with the auth, not sure, see... Maybe is the same.
With this explanation, need to set the Authorization, I think. But the problem is when I access the site, the auth is automatic, see:
My code:
var jsonObject = JSON.stringify({ "UserName": login});
// prepare the header
var postheaders = {
'Content-Type' : 'application/json',
'Content-Length' : Buffer.byteLength(jsonObject, 'utf8')
};
// the post options
var optionspost = {
host: "xxxxxxxxxx.com",
// path: '/Home/endpoint', //send the data for the endpoit with Postma works fine
method: 'POST',
headers : postheaders
};
console.info('Options prepared:');
console.info(optionspost);
console.info('Do the POST call');
// do the POST call
var reqPost = http.request(optionspost, function(res) {
console.log("statusCode: ", res.statusCode);
// uncomment it for header details
// console.log("headers: ", res.headers);
res.on('data', function(d) {
console.info('POST result:\n');
process.stdout.write(d);
console.info('\n\nPOST completed');
});
});
// write the json data
reqPost.write(jsonObject);
reqPost.end();
reqPost.on('error', function(e) {
console.error(e);
});
Obs.: This website it's from my Company (.NET) and is Integrated with IIS (Active Directory login users for authenticate), when I access, automatically is logged... I really don't know how to solve this.
Obs II.: I Try to use one anonymous new tab and use DHC online, and my post doesn't work. This application just works inside network company and with Client side (Using postman with my computer).
Obs III.: The request is from Server and the login from my server have all permissions to access this site, and when I request, is like I'm anonymous, but if I did the same with REST Client/Postman, works perfectly. I need that it works with http request from my Server.
You can use a module like ntlm-webapi which will allow you to use NTLM auth. That way the request will go through. Just make sure the user you use is authorized for that server.
var Request = require('ntlm-webapi');
var request = new Request({
url: "http://some.restful.api.org/you/want/to/call",
username: 'username',
password: 'password',
domain: 'company_domain'
});
request.get(function(err, result){
if (err) console.log (err);
console.log (result);
});
It seems that you forgot to add the Authorization header in your code
// prepare the header
var postheaders = {
'Authorization' : 'Negotiate '+ yourAccessKey,
'Content-Type' : 'application/json',
'Content-Length' : Buffer.byteLength(jsonObject, 'utf8')
};

Why does my sailsjs service return "undefined" to the calling controller action?

I have to POST to an API that someone else has developed in order to obtain an authorization code, and as I have to do it in several different contexts I thought I'd move the code for handling the POST and getting the response to a service.
The frustrating thing at the moment is that I seem to be getting back the value that I want from the API, but can't return it from the server to the calling sails controller.
Here's the service source code:
module.exports = {
getVerifyCode: function(uuid, ip_addr) {
console.log (uuid);
console.log (ip_addr);
var http = require('http'),
querystring = require('querystring'),
// data to send
send_data = querystring.stringify({
uuid : uuid,
ip_addr : ip_addr
}),
// options for posting to api
options = {
host: sails.config.api.host,
port: sails.config.api.port,
path: '/verifyCode/update',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(send_data)
}
},
json_output = "",
// post request
post_req = http.request(options, function(post_res) {
post_res.on('data', function(chunk) {
json_output += chunk;
});
post_res.on('end', function() {
var json_data = JSON.parse(json_output),
verify_code = json_data.verify_code;
console.log("code="+verify_code);
return ('vc='+verify_code);
});
});
post_req.write(send_data);
post_req.end();
}
}
And here's two relevant lines from my controller action:
var vc = verify.getVerifyCode(req.session.uuid, req.connection.remoteAddress);
console.log('vc='+vc);
The weird thing is that the controller console log gets written before the service one does:
vc=undefined
code=YoAr3ofWRIFGpoi4cRRehP3eH+MHYo3EogvDNcrNDTc=
Any ideas? I have a much simpler service running (just some string manipulation stuff); I have a feeling the issue here relates to the asynchronous nature of the API request and response.
Jasper, your correct in your assumption that it is the " asynchronous nature of the API request and response".
When you execute your http call in your verify service, node makes that call and them moves on to the rest of the code console.log('vc='+vc); and does not wait for the http call to finish.
I'm not sure what your end result should be but you can rewrite your controller / service to include the callback (this is just one options, there are many ways to do this of course, other people should suggest others)
verify.js
getVerifyCode: function(uuid, ip_addr, cb) {
// Bunch of stuff
return post_req = http.request(options, cb(post_res});
}
then in your controller
controller.js
verify.getVerifyCode(req.session.uuid, req.connection.remoteAddress, function(resps){
// code in here to execute when http call is finished
})

Resources