Connect https using nodejs - node.js

I am trying to maintain some old Node js code. I am having trouble in connecting to https url using corporate proxy.
Below code doesn't seem to work.
var https = require('https');
var options = {
hostname: 'PROXY_IP',
port : PROXY_PORT,
path : 'https://server.ourdomain.com/path/to/secure/api',
rejectUnauthorized : false,
headers: {
'Authorization': 'Basic ' + new Buffer('username:password').toString('base64'),
'Content-Type': 'application/json',
'Host' : 'https://server.ourdomain.com:443'
}
}
var responseChunk = '';
callback = function(response) {
if(response.statusCode !== 200) {
//Error occured. Handle error
}
response.on('data', function (chunk) {
responseChunk += chunk;
});
response.on('end', function () {
// Got complete response. Process and do something
});
}
var get_req = https.request(options, callback);
get_req.on('error', function(e) {
console.log("Error:" + e)
});
get_req.end();
Error after executing this is
Error:Error: socket hang up
I was able to get this working using request module. But not using https module.
What seems to be the problem?

Use request..
var request = require('request');
request({'url':'https://anysite.you.want/sub/sub','proxy':'http://yourproxy:8087'}, function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body);
}
})

Related

node.js http set request parameters

I have a node.js application and I want to call a REST api by using http.request. This is my code:
http = require("http");
const options = {
host: localhost,
port: 8103,
path: "/rest/getUser?userId=12345",
method: "GET"
};
http.request(options, function(res) {
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log('BODY: ' + chunk);
resolve(JSON.parse(chunk));
});
}).end();
The above code works fine, but I don't want to include the request parameter ?userId=12345 in the path. The path should be: /rest/getUser. How do I set the request parameter with http.request?
You can use request package, which has more features, instead of built in http client.
var request = require('request');
var url = 'http://localhost:8103/rest/getUser/';
var paramsObject = { userId:12345 };
request({url:url, qs:paramsObject}, function(err, response, body) {
if(err) { console.log(err); return; }
console.log("Response: " + response.statusCode);
});

using Node.js to make request, Yelp API error

I am writing my Node.js file now, which is to send requests to Yelp API and get the JSON response for client. I test my code in localhost.
I have seen the requesting url and both format and data are correct.
However, I get an error message when requesting this API:
connect ECONNREFUSED 127.0.0.1:443
Here is my Node.js code:
http.createServer(function (req, res) {
// data from the client
var some_data;
// send a GET request to Yelp’s API
var https = require('https');
var yelpMatch_url = encodeURI("https://api.yelp.com/v3/businesses/matches/best?some_data;
var headers = {
'Authorization': 'Bearer myAPI_KEY'
};
https.get({url: yelpMatch_url, headers: headers}, function(response) {
var body = '';
response.on('data', function (chunk) {
body += chunk;
});
response.on('end', function () {
// write response json
res.write(body);
res.end();
});
}).on('error', function(e) {
console.log(e.message);
});
}).listen(myPort);
Why this error ?
It looks you are doing the request to https on your localhost.
Make sure your server is running locally, and update the get method as follows:
https.get(yelpMatch_url, {headers: headers}, function(req, response) {
var body = '';
response.on('data', function (chunk) {
body += chunk;
});
response.on('end', function () {
// write response json
res.write(body);
res.end();
});
}).on('error', function(e) {
console.log(e.message);
});
Thanks! I figured it out. The format should be like this:
var https = require('https');
var myurl = "http://www.example.com";
var options = {
url: myurl,
headers: {
'Authorization': 'Bearer myKeyID'
}
};
https.get(options, function(response) {
... }

NodeJS http post request read timeout

I'm trying to execute the following code inside AWS Lambda which only makes a POST http request to an ElasticSearch.
The problem I'm facing is that it seems the nodejs request has a read timeout and the response is almost always cut and an error is thrown. I've checked that the problem is not related with AWS Lambda timeout which is set to 10 seconds and the code throws an error in less than a second.
As you can see, I've tried to put a timeout to 5secs but I think that's a connection timeout and not a read timeout.
What am I doing wrong?
var http = require('http');
exports.handler = (event, context, callback) => {
var options = {
hostname: '172.31.40.10',
port: 9200,
path: '/articles/es/_search?_source=reference',
method: 'POST',
headers: {
'Content-Type': 'application/json',
}
};
var req = http.request(options, function(res) {
res.setEncoding('utf8');
res.on('data', function (body) {
var parsed = JSON.parse(body);
var b = [];
for (var i = 0; i < parsed.hits.hits.length; i++) {
b.push(parsed.hits.hits[i]._source.reference);
}
var response = {
statusCode: '200',
body: JSON.stringify(b),
headers: {
'Content-Type': 'application/json',
}
};
callback(null, response);
});
});
req.on('error', function(e) {
callback(new Error('fallo'));
});
req.setTimeout(5000, function() {req.abort;})
req.on('socket', function (socket) {
socket.setTimeout(5000);
socket.on('timeout', function() {
req.abort();
});
});
req.write(MY_QUERY_HERE);
req.end();
};
I think you should let the stream of incoming data finish before performing any data manipulation.
Example :
var http = require('http');
//var _ = require('underscore');
function MyPostRequest(callback) {
var options = {
hostname:'172.31.40.10',
port:9200,
path:'/articles/es/_search?_source=reference',
method:'POST',
headers:{'Content-Type':'application/json'}
};
http.request(options, function(res) {
var tmpstore = ''; //temp. data storage
//:Store the continuous incoming data stream
res.on('data', function(d){tmpstore += d;});
//:Data reception is done, use it now...
res.on('end', function() {
var parsed = JSON.parse(tmpstore); var b = [];
for (var i = 0; i < parsed.hits.hits.length; i++) {
b.push(parsed.hits.hits[i]._source.reference);
}
/* //I suggest using underscore module :
_.each(parsed.hits.hits,function(element, index, list){
b.push(element._source.reference);
});
*/
var response = {
statusCode:'200',
body:JSON.stringify(b),
headers:{'Content-Type':'application/json'}
};
callback(null, response);
});
//:Response contained an error
res.on('error', function(e){/*error handling*/callback(e,null);});
});
}

I can't save http-headers to the file by piping these to stream in node.js

var fsHeaders = fs.createWriteStream('headers.html', 'utf-8');
var getHeaders = request('http://google.com', {method: 'HEAD'}, function (error, response, body)
{
if (error || response.statusCode !== 200)
{
return res.redirect('/');
}
if (!error && response.statusCode == 200)
{
var tester = response.body;
console.log(tester + 'response.body is EMPTY... so the headers are stored not in the "body"... \n');
var targetHeaders = response.headers;
body = body + JSON.stringify(targetHeaders);
console.log(body + 'OK! \n');
}
}).pipe(fsHeaders);
but my headers.html is empty... how to properly save response.headers to file? Can I later modify headers and sent them to the user without problem or it's restricted in some way? I want to get data from server, modify it via node, and send it to the user.
It doesn't matter if you are using request or http module. When you request headers only with {method: 'HEAD'} method body is empty but headers are resident in response stream. I guess you problem is with requiring headers and display them as [objest Object]. You need to change object to string in that matter - to simply display it with console.log or pipe it to the file.
var targetHeaders = objectToString(resp.headers, targetHeaders);
function objectToString(object, outputString)
{
var outputString = '';
for (var i in object)
{
if (object.hasOwnProperty(i))
{
outputString += i + ': ' + object[i] + ' \n';
}
}
return outputString;
}
now console.log(targetheaders); // OK! no [object Object] anymore :)
You can latter pass those headers without any problem.
First, to verify that you are using http.request
Your problem also can be because request by default returns buffer and your stream is UTF-8 format.
Also the better way "catch" your headers might be by events that are emitted by http request:
var postData = querystring.stringify({
'msg': 'Hello World!'
});
var options = {
hostname: 'www.google.com',
port: 80,
path: '/upload',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(postData)
}
};
var req = http.request(options, (res) => {
console.log(`STATUS: ${res.statusCode}`);
console.log(`HEADERS: ${JSON.stringify(res.headers)}`);
res.setEncoding('utf8');
res.on('data', (chunk) => {
console.log(`BODY: ${chunk}`);
});
res.on('end', () => {
console.log('No more data in response.');
});
});
req.on('error', (e) => {
console.log(`problem with request: ${e.message}`);
});
// write data to request body
req.write(postData);
req.end();

How to do request HTTP Digest auth with Node.JS?

I have to write some code with Node.JS for an API documentation, but I tried the last few days all the solutions I could found on the web (including Stack of course) without succes...
My API use HTTP Digest Auth and that's the problem, I was able to connect, that's was not a big deal but everytime I got the same return :
Got response : 401
HTTP Digest Authentication required for "api.example.com"
You can show my base code below without auth! Because I don't know what I can do after all the try I did :
var http = require('http')
var options = {
host: 'api.example.com',
path: '/example/1.xml',
};
var request = http.get(options, function(res){
var body = "";
res.on('data', function(data){
body += data;
})
res.on('end', function(){
console.log('Got response : ' + res.statusCode);
console.log(body);
})
res.on('error', function(e){
console.log('Got error : ' +e.message);
});
});
One of my last try was to use this module https://npmjs.org/package/request but he doesn't work too as everytime I got 401 !
For more information I was able to connect and GET the information I needed from my API with Ruby, Python, php, and Java so I'm sure my API is working well and the information I pass are correct.
I use the last stable of Node v0.10.11 !
If someone can help me or have a solution up to date i will be glad.
EDIT :
I will add some details about my test with the module Mickael/request
First Try :
var request = require('request')
var options = {
'url': 'http://api.example.fr/example/1.xml',
'auth': {
'user': 'test',
'pass': 'test',
'sendImmediately': false
}
};
var request = request.get(options, function(error, response, body){
if (!error && response.statusCode == 200){
console.log('body : ' + body)
}
else{
console.log('Code : ' + response.statusCode)
console.log('error : ' + error)
console.log('body : ' + body)
}
});
Second Try :
var request = require('request')
request.get('http://api.example.fr/example/1.xml', function(error, response, body){
if (!error && response.statusCode == 200){
console.log('body : ' + body)
}
else{
console.log('Code : ' + response.statusCode)
console.log('error : ' + error)
console.log('body : ' + body)
}
}).auth('test', 'test', false);
but the return is still the same 401
Here's your example corrected to use request as per it's API.
var options = {
uri: 'http://api.example.fr/example/1.xml',
auth: {
user: 'test',
pass: 'test',
sendImmediately: false
}
};
request(options, function(error, response, body){
if (!error && response.statusCode == 200){
console.log('body : ' + body)
}
else{
console.log('Code : ' + response.statusCode)
console.log('error : ' + error)
console.log('body : ' + body)
}
});
The request chainable style API is a bit confusing (IMHO), but I believe you can make it work that way as well.
The digest auth in the request package seems to be incomplete.
You can try out: https://npmjs.org/package/http-digest-client ,its a pretty decent lightweight implementation for the digest authentication.
If you need to do a digest auth POST with a body message to be sent you can use request in conjunction with http-digest-client. After installing both just open up http-digest-client code under node-modules and replace its use of the http package with the request package api.
Try urllib it will work with simple and disgest auth.
const httpClient = require('urllib');
const url = 'https://site.domain.com/xmlapi/xmlapi';
const options = {
method: 'POST',
rejectUnauthorized: false,
// auth: "username:password" use it if you want simple auth
digestAuth: "username:password",
content: "Hello world. Data can be json or xml.",
headers: {
//'Content-Type': 'application/xml' use it if payload is xml
//'Content-Type': 'application/json' use it if payload is json
'Content-Type': 'application/text'
}
};
const responseHandler = (err, data, res) => {
if (err) {
console.log(err);
}
console.log(res.statusCode);
console.log(res.headers);
console.log(data.toString('utf8'));
}
httpClient.request(url, options, responseHandler);
your sample is work
var request = require('request')
request.get('http://api.example.fr/example/1.xml', function(error, response, body){
if (!error && response.statusCode == 200){
console.log('body : ' + body)
}
else{
console.log('Code : ' + response.statusCode)
console.log('error : ' + error)
console.log('body : ' + body)
}
}).auth('test', 'test', false);

Resources