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"
}
});
Related
With the following cURL request I am able to successfully interact with a pulsar api to update the configurations of a function.
Working cURL Request
curl --request PUT -H "Content-Type: multipart/form-data" -F functionConfig='{"parallelism":2};type=application/json' http://pulsar-test:8080/admin/v3/functions/test/ingest/test-entity-FeedTransformer
But I'm having trouble converting to an equivalent fetch request in Node.
Note: I'm using formdata-node to import FormData.
import { FormData } from 'formdata-node'
Non Working Fetch (Bad Request)
const body = new FormData()
body.append('functionConfig', '{"parallelism":2};type=application/json')
return fetch(
'http://pulsar-test:8080/admin/v3/functions/test/ingest/test-entity-FeedTransformer',
{
body,
headers: {
Authorization: 'Bearer abcd'
},
method: 'PUT'
}
)
Apparently the form data is not being set in a way the api server can recognize.
{"reason":"Function config is not provided"}
What am I missing here?
the problem is most likely that multipart request is not recognized/not well formed, or something like that, so try using another library, here's an example with Form-Data:
import { FormData } from 'form-data';
const body = new FormData();
body.append('functionConfig', '{"parallelism":2};type=application/json')
return fetch(
'http://pulsar-test:8080/admin/v3/functions/test/ingest/test-entity-FeedTransformer', {
body,
headers: {
Authorization: 'Bearer abcd'
},
method: 'PUT'
}
)
alternatively, you could run your curl command with child-process
see: How to use curl with exec nodejs
I need to make a simple POST request to a server. It works well with curl:
curl --basic -u foo -d '' https://bar.com/path/to/smth
But when I try to do it with Node.js I get a 401 Authorization required response:
'use strict';
const https = require('https');
const auth = `Basic: ${Buffer.from('foo:myPass1234', 'utf8').toString('base64')}`;
const postData = '';
const options = {
hostname: 'bar.com',
path: '/path/to/smth',
port: '443',
method: 'POST',
headers: {
Authorization: auth,
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': postData.length
},
};
const req = https.request(options, (res) => {
res.on('data', (d) => {
//this spits a 401 html page
console.log(d.toString());
});
});
req.write(postData);
What am I doing wrong? Any help is greatly appreciated.
To debug such an issue I would recommend these steps:
use curl with the -v (verbose) option and compare http headers it uses to the ones you are using in the options.
In here the error was the colon in the Basic: … string of the Authorization header
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);
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);
I am trying to upload an image with the box API and the request module. I tried the provided curl example without any problems.
I have a request all setup like this
var request = require("request");
var fs = require("fs");
var path = require("path");
request({
url: "https://api.box.com/2.0/files/content",
method: "POST",
form: {
filename: fs.createReadStream(path.join(__dirname, "midguts.jpg")),
folder_id: "0"
},
headers: {
api_key: "<API_KEY>",
auth_token: "<AUTH_TOKEN>"
}
}, function (error, response, body) {
console.log(error);
console.log(body);
});
The problem arises when I get to the headers part. The box API call for a headers string of
"Authorization: BoxAuth api_key=API_KEY&auth_token=AUTH_TOKEN"
but I with the request module I can only send an object of key, value pairs. I also looked at the docs for nodes http.request and found it has the same issue.
So the question is, why does the API not follow the standard key pair format and how can I send a POST request that will work?
Authorization is the name of the HTTP Header (see also). This might work better:
headers: {
Authorization: "BoxAuth api_key=API_KEY&auth_token=AUTH_TOKEN"
}