I have a piece of code that's supposed to do a http get request. The program exited successfully without error, but I didn't see any response and it didn't even go inside the callback function! At first I thought it's because http is asynchronous and put a large loop in the end but that didn't work either. Does anyone know this issue? Only the first console log sendHttpRequest and 444 gets printed. I also tried the http.get but it didn't work either.
function sendHttpRequest (url, callBack) {
console.log("sendHttpRequest");
//constrct options
var options = {
host: 'www.google.com',
path: '/index.html',
method: 'GET',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
};
http.get("http://www.google.com/index.html", function(res) {
console.log("Got response: " + res.statusCode);
});
var req = http.request(options, function(res) {
console.log("333");
var output = '';
console.log(options.host + ':' + res.statusCode);
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log("DATATATAT!")
output += chunk;
});
res.on('end', function () {
console.log('222');
var obj = JSON.parse(output);
callBack(res.statusCode, obj);
});
});
req.on('error', function (err) {
console.log('error: ' + err.message);
});
req.end();
console.log("444");
}
}
Update
The grunt task terminated before the OP received a response; adding async and a callback to the task fixed it.
If I take your code outside of the function and prepend var http = require('http'); I get a response up until 222, at which point it dies with SyntaxError: Unexpected token <. Which is actually dying because you're trying to parse an HTML response as JSON.
If you paste the entire script below and run it end to end, the console dies with:
undefined:1
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
^
SyntaxError: Unexpected token <
at Object.parse (native)
at IncomingMessage.<anonymous> (/Users/you/nodetest/tmp/test.js:31:28)
at IncomingMessage.EventEmitter.emit (events.js:120:20)
at _stream_readable.js:896:16
at process._tickCallback (node.js:599:11)
The script:
var http = require('http');
console.log("sendHttpRequest");
//constrct options
var options = {
host: 'www.google.com',
path: '/index.html',
method: 'GET',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
};
http.get("http://www.google.com/index.html", function(res) {
console.log("Got response: " + res.statusCode);
});
var req = http.request(options, function(res) {
console.log("333");
var output = '';
console.log(options.host + ':' + res.statusCode);
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log("DATATATAT!")
output += chunk;
});
res.on('end', function () {
console.log('222');
// it's failing on the next line, because the output
// it's receiving from Google is HTML, not JSON.
// If you comment out this line and simply
// "console.log(output)" you'll see the HTML response.
var obj = JSON.parse(output);
callBack(res.statusCode, obj);
});
});
req.on('error', function (err) {
console.log('error: ' + err.message);
});
req.end();
console.log("444");
Related
curl -d "m_payment_id=m_payment_id-xxxxxxxxxxxxxxxxxyyy&pf_payment_id=990396&payment_status=COMPLETE&item_name=Subscription&item_description=Monthly+Subscription&amount_gross=99.00&amount_fee=-6.74&amount_net=92.26&custom_str1=&custom_str2=&custom_str3=&custom_str4=&custom_str5=&custom_int1=&custom_int2=&custom_int3=&custom_int4=&custom_int5=&name_first=&name_last=&email_address=christo%40g4-ape.co.za&merchant_id=0000000&token=0000000-0000-0000-3a83-25bc733a307b&billing_date=2020-02-21&signature=3895d0769b56862b842da5067af4483f" -X POST https://sandbox.somedomain.co.za/what/something/validate
My attempt:
const https = require("https");
const querystring = "m_payment_id=m_payment_id-xxxxxxxxxxxxxxxxxyyy&pf_payment_id=990396&payment_status=COMPLETE&item_name=Subscription&item_description=Monthly+Subscription&amount_gross=99.00&amount_fee=-6.74&amount_net=92.26&custom_str1=&custom_str2=&custom_str3=&custom_str4=&custom_str5=&custom_int1=&custom_int2=&custom_int3=&custom_int4=&custom_int5=&name_first=&name_last=&email_address=christo%40g4-ape.co.za&merchant_id=0000000&token=0000000-0000-0000-3a83-25bc733a307b&billing_date=2020-02-21&signature=3895d0769b56862b842da5067af4483f";
return new Promise((resolve, reject) => {
const options = {
hostname: 'sandbox.somedomain.co.za',
port: 443,
path: 'what/something/validate',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(querystring)
}
};
const req = https.request(options, (res) => {
console.log('statusCode: ' + res.statusCode);
console.log('headers: ' + JSON.stringify(res.headers));
res.setEncoding('utf8');
let data = '';
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
console.log('BODY: ' + data);
});
resolve('Success');
});
req.on('error', (e) => {
console.log('problem with request: ' + e.message);
reject(e.message);
});
// write data to request body
req.write(querystring);
req.end();
});
I keep getting a statusCode 400 on the NodeJS code, the curl works fine. The hostname hs obviously been changed for security.
Can someone please advise me on what I'm doing wrong here?
Content-Length is reqired when you are sending the body while posting. In your case all the info is getting passed as query string parameter so you can get rid of the headers alltogather.
Also, you should be resolving inside res.on('end'. THe way you are doing it will finish the function before it even finishes execution.
I'm trying to create an Azure function using nodeJS, but when I make a call to an https API I get an error message.
Is it possible to make a HTTPS call from azure function?
Here is my code
const https = require('https');
const querystring = require('querystring');
module.exports = async function (context, req) {
if (req.query.accessCode || (req.body && req.body.accessCode)) {
var options = {
host: 'api.mysite.com',
port: 443,
path: '/oauth/access_token',
method: 'POST'
};
var postData = querystring.stringify({
client_id : '1234',
client_secret: 'xyz',
code: req.query.accessCode
});
var req = https.request(options, function(res) {
context.log('STATUS: ' + res.statusCode);
context.log('HEADERS: ' + JSON.stringify(res.headers));
res.on('data', function (chunk) {
context.log('BODY: ' + chunk);
});
});
req.on('error', function(e) {
context.log('problem with request: ' + e.message);
});
req.write(postData);
req.end();
context.res = {
status: 200,
body: "Hello " + (req.query.accessCode)
};
} else {
context.res = {
status: 400,
body: "Please pass a name on the query string or in the request body"
};
}
context.done();
};
I get an error but I do not see any error on the console, also if I comment all the https call it works fine and I can see the Hello message on the screen.
Two points to fix
Delete context.done();. See Azure document.
If your function uses the JavaScript async function declaration (available using Node 8+ in Functions version 2.x), you do not need to use context.done(). The context.done callback is implicitly called.
Rename your https.request like var myReq = https.request(options, function(res).
There's a name conflict causing error as function has a built-in req object declared.
It's possible, here is an example of how to make a request to an Azure AD v2 token endpoint (I'd assume you are trying to do something similar):
var http = require('https');
module.exports = function (context, req) {
var body = "";
body += 'grant_type=' + req.query['grant_type'];
body += '&client_id=' + req.query['client_id'];
body += '&client_secret=' + req.query['client_secret'];
body += '&code=' + req.query['code'];
const options = {
hostname: 'login.microsoftonline.com',
port: 443,
path: '/ZZZ920d8-bc69-4c8b-8e91-11f3a181c2bb/oauth2/v2.0/token',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': body.length
}
}
var response = '';
const request = http.request(options, (res) => {
context.log(`statusCode: ${res.statusCode}`)
res.on('data', (d) => {
response += d;
})
res.on('end', (d) => {
context.res = {
body: response
}
context.done();
})
})
request.on('error', (error) => {
context.log.error(error)
context.done();
})
request.write(body);
request.end();
};
The difference is - the function is not async module.exports = function
I believe your issue is:
You should use the Node.js utility function util.promisify to turn error-first callback-style functions into awaitable functions.
link
how to use Q to make it wait until previous response has come from the server.
What I am looking to do here is compare the response from test server and production server for the same request.
I get the responses back from both the servers, but unable to compare them since the assert statement is executed before the response comes back.
Any one know what I am doing wrong. heres the code.
var Q = require('q');
var path='';
var prodResponse = '';
var tstReponse = '';
Q.fcall(readFile())
.then(secondFunction())
.then(thirdFunction())
.then(function(){
console.log("prodResponse: "+prodResponse);
console.log("tstResponse: "+tstResponse);
assert.strictEqual(prodResponse, tstResponse)
})
.catch(function(){
console.log('error occurred');
})
.done();
function readFile(){
fs.readFile('hostname.json', function (err, data) {
if (err) return console.error(err);
path = JSON.parse(data);
return JSON.parse(data);
});
}
function secondFunction(){
var prodOptions = {
hostname: 'somehostname.com',
port: 80,
path: "/path?"+path.path,
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=UTF-8'
},
auth : ''
};
return http.request(prodOptions, function(res) {
console.log('Prod');
res.setEncoding('utf8');
res.on('data', function (chunk) {
prodResponse = chunk;
return chunk;
});
res.on('end', function() {
console.log('No more data in response.');
})
}).on('error', function(e) {
console.log('problem with request: ' + e.message);
}).end();
}
function thirdFunction(){
// same a second, only difference is the response http.
}
There is multiple errors in your code
Q.fcall(readFile())
Your q variable is q and not Q. So this line will crash because Q is undefined (javascript is case sensitive).
Then, readFile doesn't return any promise (in fact, it returns nothing). So the q library can't use anything to wait the end of any asynchronous work. The then callbacks will be fired immediatly.
You can use Q.ninvoke to make your readFile function return a promise, and you can use Q.defer to create and return a promise from your secondFunction:
var Q = require('q');
var path='';
var prodResponse = [];
var tstReponse = '';
readFile()
.then(secondFunction())
.then(thirdFunction())
.then(function(){
console.log("prodResponse: "+prodResponse);
console.log("tstResponse: "+tstResponse);
assert.strictEqual(prodResponse, tstResponse)
})
.catch(function(){
console.log('error occurred');
})
.done();
function readFile(){
return Q.ninvoke(fs, 'readFile', 'hostname.json').then(function (data) {
path = JSON.parse(data);
return path;
}, function (err) {
console.error(err);
});
}
function secondFunction(){
var prodOptions = {
hostname: 'somehostname.com',
port: 80,
path: "/path?"+path.path,
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=UTF-8'
},
auth : ''
};
var defer = Q.defer();
var chunks = [];
http.request(prodOptions, function(res) {
console.log('Prod');
res.setEncoding('utf8');
res.on('data', function (chunk) {
chunks.push(chunk);
});
res.on('end', function() {
console.log('No more data in response.');
prodResponse = chunks.join('');
defer.resolve(prodResponse);
})
}).on('error', function(e) {
console.log('problem with request: ' + e.message);
defer.reject(e);
}).end();
return defer.promise;
}
function thirdFunction(){
// same a second, only difference is the response http.
}
Guys I'm having trouble requesting to this URL.. It seems fine, but I always get the error ECONNRESET.
I wrote a little script in ruby and it worked fine. With cURL in the terminal also works.
I tried all the solutions on a lot of issues and stack overflow threads... Like these:
https://github.com/joyent/node/issues/5360
https://github.com/joyent/node/issues/5119
Any idea what it might be?
The url is: https://ecommerce.cielo.com.br/servicos/ecommwsec.do
var https = require('https');
var options = {
host: 'ecommerce.cielo.com.br',
path: '/servicos/ecommwsec.do',
//This is what changes the request to a POST request
method: 'GET',
};
https.globalAgent.options.secureProtocol = 'SSLv3_method';
callback = function(response) {
var str = ''
response.on('data', function (chunk) {
str += chunk;
});
response.on('end', function () {
console.log(str);
});
}
var req = https.request(options, callback);
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
How are you ??
Let's try this solution.
app.js
Change your options:
var options = {
host: 'ecommerce.cielo.com.br',
path:'/servicos/ecommwsec.do',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(body),
'user-agent': 'node.js'
}
};
https.globalAgent.options.secureProtocol = 'SSLv3_method';
try{
var req = https.request(options, function(res)
{
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log("body: " + chunk);
}).on('end', function(cieloResponse){
console.log( cieloResponse);
});
console.log('Response:' + res);
});
req.end();
}catch(err){
console.log('ERRO: '+ err);
}
I am getting a "socket hang up" error while doing a post request. I am not able to resolve it.
sparqlQ = getSPARQLPrefix() + query_string;
console.log(sparqlQ)
var options = {
host: process.env['SESAME_HOST'],
port: process.env['SESAME_PORT'],
method: 'POST',
path:
'/openrdf-sesame/repositories/myReo?update=' +
encodeURIComponent(sparqlQ) +
'&content-type=application/sparql-results+json',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Accept': 'application/sparql-results+json',
},
};
var req = http.request(options, function(res) {
var data = "";
res.on('data', function (chunk) {
data += chunk;
});
res.on('error', function (error) {
console.log(error)
});
res.on('end', function () {
console.log(data)
req.end();
callback(null);
});
}).on('error', function(e) {
console.alert("Error getting sesame response [%s]", e.message);
req.end();
callback(e.message);
return
});
What am I doing wrong? Please help!
Two things to mention here.
You are not calling req.end() on your http request.
refer this documentation on the http module of node.js.
With http.request() one must always call req.end() to signify that
you're done with the request - even if there is no data being written
to the request body.
on the req.error event you are calling console.alert which i think should be console.log
Here is a sample code
http = require("http");
var options = {
host: "localhost",
port: 80,
method: 'POST'
};
var req = http.request(options, function(res) {
var data = "";
res.on('data', function (chunk) {
data += chunk;
});
res.on('error', function (error) { });
res.on('end', function () {
console.log(data)
req.end();
console.log(null);
});
}).on('error', function(e) {
console.log("Error getting sesame response [%s]", e.message);
req.end();
console.log(e.message);
return
});
req.end();