Very simple API request fails with Request.js, works with Curl - node.js

Simple query to an API, the curl request works, but fails when I try to utilize the request NPM module to perform the request.
Curl:
curl "https://api.squarespace.com/1.0/commerce/orders?modifiedAfter=2019-11-01T12:00:00Z&modifiedBefore=2019-11-15T12:00:00Z" \
-H "Authorization: Bearer abcde"
Request:
const response = await request({
method: 'GET',
uri:
'https://api.squarespace.com/1.0/commerce/orders?modifiedAfter=2019-11-01T12:00:00Z&modifiedBefore=2019-11-15T12:00:00Z',
headers: {
Authorization: 'Bearer abcde'
}
});
Request succeeded with curl, immediate error with request js reporting status code 400. Can you tell me what is amiss with my request usage, and how it even differs from the request generated by curl?
Latest version of request is being used.

The key in your request options must be 'url' and not 'uri'
And don't forget to set the callback function that wille be called (so you will also see the error returned when there is one)
const request = require('request');
const options = {
url: 'https://api.squarespace.com/1.0/commerce/orders?modifiedAfter=2019-11-01T12:00:00Z&modifiedBefore=2019-11-15T12:00:00Z',
headers: {
'Authorization': `Bearer abcde`
}
};
function callback(error, response, body) {
console.error('error:', error);
console.log('statusCode:', response && response.statusCode);
console.log('body:', body);
}
request(options, callback);

Related

Pass Access Token to API in Node

I am learning Node by developing an application that would hit the relevant server and extract its data.
Here, I am stuck as the relevant server demand to pass access token, and I'm not able to extract data successfully.
Here is my code
var options = {
method: 'GET',
url: 'any url',
auth : {
accessToken : "token here"
},
headers: {
'Accept': 'application/json'
}
}
But doing this i'm getting error Error: no auth mechanism defined
Access token seems to be perfect.
Sorry if this has been asked already but I cannot seem to find a straight answer.
Thanks for your efforts and time.
Try this :
var req = {
host: 'YOUR_URL',
method: 'GET',
headers: {
Authorization: your token
'Content-Type': 'application/json'
}
}
request(req, function(error, response, body) {
console.log('error:', error); // Print the error if one occurred
console.log('statusCode:', response && response.statusCode); // Print the response status code if a response was received
console.log('body:', body);
}

github search api not giving results when called from request module in nodejs

I am trying to fetch the results from all repositories of my organisation under a search category. The results are fetched properly when I use the curl command as shown below
curl -H "Authorization: token ****" -i https://api.github.com/search/code?q=org:<org>+<search_param>
But when I try to run it programmatically in nodejs via the request module it is not returning any results.
My code is as shown below
const request = require("request");
const options = {
url:'https://api.github.com/search/code?q=org:<org>+<search_param>'
headers: {
"Autorization": "token ***",
"User-Agent": "request"
},
json:true
}
console.log(options);
request.get(options, function (error, response, body) {
console.log('error:', error); // Print the error if one occurred
console.log('statusCode:', response && response.statusCode); // Print the response status code if a response was received
console.log('body:', body); // Print the HTML for the Google homepage.
});
The output for the above code is as below
body: {"total_count":0,"incomplete_results":false,"items":[]}
Please let me know what is wrong with the above code or if I am missing anything.
I was able to solve this by using the axios module instead of request module as the request module does not send the Authorization hader. Got a reference from Nodejs request module doesn't send Authorization header.
The updated code which works is as follows
const axios = require("axios");
const options = {
method:"get",
url:'https://api.github.com/search/code?q=org:<org>+<searchtoken>',
headers: {
"Authorization": "token ***",
"User-Agent": "abc"
}
}
console.log(options);
axios(options).then(function ( response) {
console.log('statusCode:', response); // Print the response status code if a response was received
// console.log('body:', body); // Print the HTML for the Google homepage.
}).catch(function (error) {
console.log(error);
});
Thanks #mehta-rohan for the help

Unable to exchange code for access token in node.js. Mailchimp API

I am trying to use OAuth2 with the Mailchimp API, and I am following their documentation to the letter, but I am unable to complete step 4. At this step, I exchange the code I received from the authorization screen for the token. Per the documentation, this can be done in curl like so:
curl --request POST \
--url 'https://login.mailchimp.com/oauth2/token' \
--data "grant_type=authorization_code&client_id={client_id}&client_secret={client_secret}&redirect_uri={encoded_url}&code={code}" \
--include
I attempted to convert this to work on node.js by writing this:
var dataString = 'grant_type=authorization_code&client_id=' + clientid + '&client_secret=' + clientsecret + '&redirect_uri=' + encodedurl + '&code=' + url.parse(req.url, true).query.code;
var options = {
url: 'https://login.mailchimp.com/oauth2/token',
method: 'POST',
data: dataString
};
function callback(error, response, body) {
if (!error) {
console.dir(JSON.stringify(body));
}
else{
console.dir(error);
}
}
request(options, callback);
When I make the request.debug = true, I see that I am getting a 400 error. The message sent to the console is a bunch of garbled characters though. When I use these same variables and endpoints to authenticate through Postman though, it works fine, so the issue is not with the variables or the API itself.
I am not entirely sure what I am doing wrong here. The request I am making seems almost identical what is written in curl in the documentation. So where am I going wrong?
Hmm, did you forget to define request?
var request = require("request");
Finally figured it out. The issue was in the header of the request. There are two ways to fix this. The first is to use "form" instead of "data". Request includes a "content-type: x-www-form-urlencoded" header automatically if the option "form" is used.
var options = {
url: 'https://login.mailchimp.com/oauth2/token',
method: 'POST',
form: dataString
};
I am not sure what header is used when the "data" option is used, or if no content-type is declared at all. Either way, if you choose to continue to use the "data" option, you can manually declare a content-type header. This is the second possible solution.
var options = {
url: 'https://login.mailchimp.com/oauth2/token',
method: 'POST',
headers:
{ 'Content-Type': 'application/x-www-form-urlencoded' },
body: dataString
};
After alot of tries, I figured out. You can use code only once. So make sure you use code you get from redirect URI only once.
With new code use this code
const dataString = "grant_type=authorization_code&client_id="+client_id+"&client_secret="+client_secret+"&redirect_uri="+redirect_uri+"&code="+req.body.code
var options = {
url: 'https://login.mailchimp.com/oauth2/token',
method: 'POST',
headers:
{
'Content-Type': 'application/x-www-form-urlencoded',
},
form: dataString
};
function callback(error, response, body) {
if (!error) {
let str = JSON.stringify(body)
res.setHeader("Content-Type", "application/json; charset=utf-8")
res.send(body)
}
else{
console.dir(error);
res.send(error)
}
}
request(options, callback);

request.js fails where CURL succeeds for GET request with Authorization header

I can make a GET request with an Authorization header from curl but not from request or https in Node.js. The server returns status 200 with curl but 500 with request or https. How might the call from request or https be different from curl? How might the server be reading them differently?
The following cURL succeeds from command line:
curl -H "Authorization: Bearer abc123def456" https://api.domain.com/path/to/resource
But the same request fails with request.js in Node
var options = {
type: 'get',
url: "https://api.domain.com/path/to/resource",
headers: {
"Authorization": " Bearer abc123def456"
}
}
request(options, function (err, response, body) {
assert.equal(response.statusCode, 200) ; // 500 internal error
})
The following also fails with request.js using the auth option:
var options = {
type: 'get',
url: "https://api.domain.com/path/to/resource",
auth: {
"bearer": "abc123def456"
}
}
request(options, function (err, response, body) {
assert.equal(response.statusCode, 200) ; // 500 internal error
})
It also fails when using https without request.js:
var options = {
host: 'api.domain.com',
port: 443,
path: '/path/to/info',
method: 'GET',
headers: {
"Authorization": " Bearer abc123def456"
}
}
var req = https.request(options, function (res) {
res.setEncoding('utf8');
res.on('end', function () {
assert.equal(res.statusCode, 200) // 500 internal error
})
});
req.on('error', function (e) {
console.log('problem with request: ' + e.message);
});
req.end();
But the curl requests succeeds if shelled out from Node:
exec("curl -H "Authorization: Bearer abc123def456" https://api.domain.com/path/to/resource", function (error, stdout, stderr) {
var obj = JSON.parse(stdout) // successfully retrieved and parsed
});
request-debug gives the following info:
{ request:
{ debugId: 1,
uri: 'https://api.domain.com/path/to/resource',
method: 'GET',
headers:
{ host: 'api.domain.com',
authorization: 'Bearer abc123def456' } } }
500 internal error generally means there is an error at the server side . So, ideally, you should be taking a look at the server logs.
However, if you don't have access to those logs, look at the difference between the requests sent by each one of the options you tried:
Module: Request (with manually specified auth header):
GET /path/to/resource HTTP/1.1
Authorization: Bearer abc123def456
host: api.domain.com
Module: Request (with explicitly specified auth header):
GET /path/to/resource HTTP/1.1
host: api.domain.com
authorization: Bearer abc123def456
Module: HTTP (with manually specified auth header):
GET /path/to/info HTTP/1.1
Authorization: Bearer abc123def456
Host: api.domain.com
Curl:
GET /path/to/resource HTTP/1.1
Host: api.domain.com
User-Agent: curl/7.51.0
Accept: */*
Authorization: Bearer abc123def456
It is quite evident that the rest of the modules do not send the HTTP headers 'User-Agent' and 'Accept'. So, it could be the case that the app running on the server is trying to parse at least one of this and failing.

How do I duplicate this CURL request within nodejs?

I am trying to duplicate the following CURL request within nodejs using request-promise (eventually, I need to use promises so I would prefer this method):
curl -H "Authorization: Token token=[API Key]" -H "Accept: application/vnd.moonclerk+json;version=1" https://api.moonclerk.com/customers
The following code snippet shows my attempt:
var rp = require('request-promise');
var querystring = require('querystring');
//this is what I think is causing me trouble
var bodyHeaders = querystring.stringify({
"Authorization": "Token token=[token taken out in code snippet]",
"Accept": "application/vnd.moonclerk+json;version=1"
});
var options = {
uri: 'https://api.moonclerk.com/customers',
method: 'GET',
body: bodyHeaders
};
var cb = function () {
return function (response) {
console.log("response: ", response);//this should spit out the JSON text I'm looking for
}
}
rp(options).then(cb())
But I am getting Possibly unhandled StatusCodeError: 401 - HTTP Token: Access denied. in the nodejs console as a response. What's the issue here?
PS -- Note that my uri is an HTTPS (i.e., 'https://api.moonclerk.com/customers'); is this what's causing the problem?
You can't pass HTTP headers in the request body, server can't recognize them there. See https://github.com/request/request#custom-http-headers for correct usage of the request library.
var options = {
// ...
headers: {
"Authorization": "Token token=[token taken out in code snippet]",
"Accept": "application/vnd.moonclerk+json;version=1"
}
});

Resources