I get a JWT token after authenticating on an API with a POST req.
With that token, I can make a successful curl call from my command prompt:
curl --request GET https://corpURL/customer/wlsAccountManagement/v1/billingAccount/23435657 --header "env: it04" --header "Authorization: Bearer tokenstring..."
But when I try to exec this in node, it fails with Received HTTP code 503 from proxy after CONNECT.
I even tried a basic curl in the command prompt and it works:
curl -v https://corpURL/customer/wlsAccountManagement/v1/billingAccount/23435657
It just tells me I am unauthorized {"message":"Unauthorized"}, which is correct.
In node, I can't even get the {"message":"Unauthorized"}, it still gives me Received HTTP code 503 from proxy after CONNECT.
The reason I'm using curl is because I can see more info. Using axios it gives me a "socket hang up" error.
I have been trying to get this to work and searching online for a solution for over a day. Does anyone have any idea what's going on here? Why does it work in the command prompt but not in node? Thanks!
For anyone who can't get an exec with curl to work in node, or using the packages axios or request, use the https package in node like so:
const options = {
hostname: 'hostDomain', // no https protocol
port: 443,
path: '/path/to/get',
method: 'GET',
headers: {
Authorization: `Bearer tokenString`,
'Content-Type': 'application/json',
},
};
const req = https.request(options, response => {
response.on('data', d => {
process.stdout.write(d);
});
});
req.on('error', e => {
console.error(e);
});
req.end();
This was the only way I was able to get the response so far, in node. I may tweak the structure as it doesn't seem that clean, but it works! You may also need to set the env var for your cert file NODE_EXTRA_CA_CERTS=cert.pem as I already had. Peace.
EDIT
I found a solution with axios, you need to create instances with a baseURL like the https request has it:
const axiosInstance = axios.create({
baseURL: 'https://corpURL',
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json',
env: 'it04',
},
});
axiosInstance
.get('/get/path')
.then(response => console.log('response', response.data))
.catch(err => console.log('err', err));
Related
I'm trying to upload an image from my computer to Cloudflare Images using Node and the fetch API. They provided me with a curl command that works fine.
curl -X POST -F file=#./<file_name> -H "Authorization: Bearer <api_token>" https://api.cloudflare.com/client/v4/accounts/<domain_id>/images/v1
When I tried to convert it to fetch, Cloudflare keeps sending me a 400 in their response.
const cloudflarePostBody = new FormData();
cloudflarePostBody.append("file", fs.createReadStream("testing.jpeg"));
const cloudflareResponse = await fetch("https://api.cloudflare.com/client/v4/accounts/<my_id>/images/v1", {
method: "POST",
headers: {
Authorization: `Bearer ${cloudflareApiToken}`,
"Content-Type": "multipart/form-data"
},
body: cloudflarePostBody,
});
My guess is that I'm doing something wrong with how I'm reading the file with createReadStream, but a lot of the examples I've looked up showed exactly that. Does anyone have any advice? Thanks in advance.
Try fs.readFile() instead of fs.createReadStream():
fs.readFile("testing.jpeg", (err, data) => {
if (err) throw err;
cloudflarePostBody.append("file", new Blob([data]), "testing.jpeg");
});
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);
So far I have this command to use in the terminal to make a GET request to readme.io api
curl https://dash.readme.io/api/v1 -X GET -u API_KEY:
PASSWORD VALUE is empty, the curl command works just fine in the terminal.
How do I do that with node.js
I have this.
const options = {
method: 'GET',
headers: {
'Authorization': 'Basic API_KEY:'
}
};
fetch('https://dash.readme.io/api/v1', options)
.then(res => res.text())
.then(body => console.log(body))
.catch(err => console.log('ERROR', err))
but it returns:
{"error":"Unauthorized","errors":null}
Can you please tell me what part did I mistaken?
Thanks in advance.
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.