I am trying to make a HTTP get request, but nothing is being returned as text. Here is my code
const http = require('http');
const ws = require('ws');
const wss = new ws.Server({noServer: true});
var XMLHttpRequest = require('xhr2');
function accept(req, res) {
console.log("got request")
wss.handleUpgrade(req, req.socket, Buffer.alloc(0), function(ws) {
//party name, sockets on party, limit 2
ws.on('message', function (msg) {
var message = JSON.parse(msg.toString())
if(message.type==='add') {
//do later
} else if(message.type==='start') {
httpGetAsync('192.168.26.23', "/startRelay")
} else if(message.type==='stop') {
httpGetAsync('92.168.26.23', "/stopRelay")
} else if(message.type==='status') {
httpGetAsync('92.168.26.23', "/")
}
});
ws.on('close', function () {
console.log('closed')
});
ws.on('error', function(error){
console.log('error - ' + JSON.stringify(error));
});
})
}
function httpGetAsync(theUrl, path) {
var options = {
host: theUrl,
path: path,
method: "GET",
}
callback = async function(response) {
var str = ''
response.on('data', function (chunk) {
str += chunk;
});
response.on('end', function () {
console.log(JSON.parse(str));
});
};
http.request(options, callback).end();
}
http.createServer(accept).listen(3000);
Here is what 192.168.26.23 has in it (if you type it up from my wifi onto google, this is what shows - and this data is what I need to get in a string)
{"success":true,"ms_left":0,"relayStarted":false}
Related
I'm trying to get my function to return the http get request, however, whatever I do it seems to get lost in the ?scope?. I'm quit new to Node.js so any help would be appreciated
function getData(){
var http = require('http');
var str = '';
var options = {
host: 'www.random.org',
path: '/integers/?num=1&min=1&max=10&col=1&base=10&format=plain&rnd=new'
};
callback = function(response) {
response.on('data', function (chunk) {
str += chunk;
});
response.on('end', function () {
console.log(str);
});
//return str;
}
var req = http.request(options, callback).end();
// These just return undefined and empty
console.log(req.data);
console.log(str);
}
Of course your logs return undefined : you log before the request is done. The problem isn't scope but asynchronicity.
http.request is asynchronous, that's why it takes a callback as parameter. Do what you have to do in the callback (the one you pass to response.end):
callback = function(response) {
response.on('data', function (chunk) {
str += chunk;
});
response.on('end', function () {
console.log(req.data);
console.log(str);
// your code here if you want to use the results !
});
}
var req = http.request(options, callback).end();
Simple Working Example of Http request using node.
const http = require('https')
httprequest().then((data) => {
const response = {
statusCode: 200,
body: JSON.stringify(data),
};
return response;
});
function httprequest() {
return new Promise((resolve, reject) => {
const options = {
host: 'jsonplaceholder.typicode.com',
path: '/todos',
port: 443,
method: 'GET'
};
const req = http.request(options, (res) => {
if (res.statusCode < 200 || res.statusCode >= 300) {
return reject(new Error('statusCode=' + res.statusCode));
}
var body = [];
res.on('data', function(chunk) {
body.push(chunk);
});
res.on('end', function() {
try {
body = JSON.parse(Buffer.concat(body).toString());
} catch(e) {
reject(e);
}
resolve(body);
});
});
req.on('error', (e) => {
reject(e.message);
});
// send the request
req.end();
});
}
Shorter example using http.get:
require('http').get('http://httpbin.org/ip', (res) => {
res.setEncoding('utf8');
res.on('data', function (body) {
console.log(body);
});
});
from learnyounode:
var http = require('http')
http.get(options, function (response) {
response.setEncoding('utf8')
response.on('data', console.log)
response.on('error', console.error)
})
'options' is the host/path variable
from learnyounode:
var http = require('http')
var bl = require('bl')
http.get(process.argv[2], function (response) {
response.pipe(bl(function (err, data) {
if (err)
return console.error(err)
data = data.toString()
console.log(data)
}))
})
I think it's too late to answer this question but I faced the same problem recently my use case was to call the paginated JSON API and get all the data from each pagination and append it to a single array.
const https = require('https');
const apiUrl = "https://example.com/api/movies/search/?Title=";
let finaldata = [];
let someCallBack = function(data){
finaldata.push(...data);
console.log(finaldata);
};
const getData = function (substr, pageNo=1, someCallBack) {
let actualUrl = apiUrl + `${substr}&page=${pageNo}`;
let mydata = []
https.get(actualUrl, (resp) => {
let data = '';
resp.on('data', (chunk) => {
data += chunk;
});
resp.on('end', async () => {
if (JSON.parse(data).total_pages!==null){
pageNo+=1;
somCallBack(JSON.parse(data).data);
await getData(substr, pageNo, someCallBack);
}
});
}).on("error", (err) => {
console.log("Error: " + err.message);
});
}
getData("spiderman", pageNo=1, someCallBack);
Like #ackuser mentioned we can use other module but In my use case I had to use the node https. Hoping this will help others.
This is my solution, although for sure you can use a lot of modules that give you the object as a promise or similar. Anyway, you were missing another callback
function getData(callbackData){
var http = require('http');
var str = '';
var options = {
host: 'www.random.org',
path: '/integers/?num=1&min=1&max=10&col=1&base=10&format=plain&rnd=new'
};
callback = function(response) {
response.on('data', function (chunk) {
str += chunk;
});
response.on('end', function () {
console.log(str);
callbackData(str);
});
//return str;
}
var req = http.request(options, callback).end();
// These just return undefined and empty
console.log(req.data);
console.log(str);
}
somewhere else
getData(function(data){
// YOUR CODE HERE!!!
})
After I updated to 6.9.2 from 4.4.0, my node.js file is crashing on client disconnect with something like:
this.ee._events.hasOwnProperty undefined at ultron\index.js:80 at process._tickCallback (internal/process/next_tick.js:98:9)
If I rollback to 4.4.0, it works correctly again. I am running this from nodemon server on Windows OS.
var server = require('http').createServer();
var io = require('socket.io')(server);
var http = require('http');
var querystring = require('qs');
io.on('connection', function(client){
var host = client.request.headers.host.split(':');
client.host = host[0];
console.log('new connection');
client.on('call', function(socketData){
if(socketData == "undefined" || !socketData.controller) {
return;
}
var path = stripHostFromPath(client.host, socketData.controller);
requestData(client.host, path, client.request.headers.cookie, 'GET',
function (body) {
var controllerSlices = socketData.controller.split('/');
var controller = controllerSlices[controllerSlices.length -1].replace('?', "");
var controllerObj = querystring.parse(controller);
var data = IsJsonString(body);//return json if true
if (controllerObj && controllerObj.f == 'updateUser') {
if (data != false) {
client.user_id = data.userId;
io.sockets.sockets['user_id'] = client.user_id;
}
}
if (data != false) {
if (data.broadcast) {
for (var i=0;i<data.broadcast.length;i++) {
//check if the user is connected
for (var k=0;k<io.sockets.sockets.length;k++) {
if (io.sockets.sockets[k]['user_id'] == data.broadcast[i]) {
io.sockets.sockets[k].emit(data.broadcastEvent, data.broadcastData);
}
}
}
}
}
});
});
client.on('disconnect', function(){
console.log('client disconected');
});
});
console.log('server listed on port 3000');
server.listen(3000);
function requestData(host, path, cookie, method, callbacks, postData) {
if (!method) method = 'POST';
if (!cookie) cookie = '';
var options = {
host: host,
port: '80',
path: path,
method: method,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Cookie': cookie
}
};
if (postData) {
postData = querystring.stringify( JSON.parse(postData) );
options.headers['Content-Length'] = Buffer.byteLength(postData);
}
try {
var req = http.request(options, function (res) {
// response is here
//console.log(res.statusCode);
//check if request was ok.
var body = '';
res.setEncoding('utf8');
res.on('data', function (chunk) {
body += chunk;
});
res.on('end', function () {
callbacks(body);
});
res.on('error', function(e){
console.log(e);
});
});
if (postData) {
req.write(postData);
}
req.end();
}
catch(e) {
console.log('requestData error:');
console.log(e);
}
}
It sounds like you have an older version of socket.io installed. By upgrading to the latest version, that should update engine.io which will update ws which will update its ultron dependency to 1.0.2, where the issue is fixed.
Hi I am trying to get a response via a http using the callback method. But I get an error saying callback is not a function.
module.exports.ipLookup = function (res, callback) {
var http = require('http');
var str = '';
var options = {
host: 'ip-api.com',
port: 80,
path: '/json/',
method: 'POST'
};
var str= "";
var req = http.request(options, function (res) {
res.on('data', function (body) {
str += body;
});
res.on('end', function () {
callback(str);
});
});
req.end();
return str;
}
What is should to id return the json api response via ip-api.com. If anyone can help me on this it would be greatly appreciated.
In the other file you are loading the function from you need to ensure the callback parameter is used. See snippet below
var Lookup = require('./ip');
Lookup.ipLookup(function (response) {
console.log(response) // check if response is valid
})
You need to change the exported function to only accept one parameter as the first parameter is not used inside function body like so.
module.exports.ipLookup = function (callback) {
var http = require('http');
var str = '';
var options = {
host: 'ip-api.com',
port: 80,
path: '/json/',
method: 'POST'
};
var req = http.request(options, function (res) {
res.on('data', function (body) {
str += body;
});
res.on('end', function () {
return callback(str);
});
});
req.end();
}
I have 2 asynchronous functions on gives me some urls and other one gives me the content I need from the url and one that writes the content I need to an file, but it write to file first and then it gives me the content I need to write, how can I get him to write to file after I get the content I need. Thanks
var http = require('http');
var fs = require('fs');
var list = {};
var k = 0;
function getContent(url){
var options = {
host: 'www.exammple.org',
path: url
}
var request = http.request(options, function (res) {
var data = '';
res.on('data', function (chunk) {
data += chunk;
});
res.on('end', function () {
list[k] = data;
k++;
});
});
request.on('error', function (e) {
console.log(e.message);
});
request.end();
}
var options = {
host: 'www.example2.org',
path: '/mypath'
}
var request = http.request(options, function (res) {
var data = '';
res.on('data', function (chunk) {
data += chunk;
});
res.on('end', function () {
///Here I get some urls from data
data = data.split(";");
for(key in data){
data = data.split('href=\"')[1].split('"')[0];
getContent(data[key]);
}
writeToFile();
}
});
});
request.on('error', function (e) {
console.log(e.message);
});
function writeToFile(){
fs.writeFile("file.txt", JSON.stringify(list), function(err) {
if(err) {
console.log(err);
} else {
console.log("The file was saved");
}
});
}
request.end();
I want to test a asynchronous javascript function that runs in node.js and makes a simple request to a http api:
const HOST = 'localhost';
const PORT = 80;
http = require('http');
var options = {
host: HOST,
port: PORT,
path: '/api/getUser/?userCookieId=26cf7a34c0b91335fbb701f35d118c4c32566bce',
method: 'GET'
};
doRequest(options, myCallback);
function doRequest(options, callback) {
var protocol = options.port == 443 ? https : http;
var req = protocol.request(options, function(res) {
var output = '';
res.setEncoding('utf8');
res.on('data', function(chunk) {
console.log(chunk);
output += chunk;
});
res.on('error', function(err) {
throw err;
});
res.on('end', function() {
var dataRes = JSON.parse(output);
if(res.statusCode != 200) {
throw new Error('error: ' + res.statusCode);
} else {
try {
callback(dataRes);
} catch(err) {
throw err;
}
}
});
});
req.on('error', function(err) {
throw err;
});
req.end();
}
function myCallback(dataRes) {
console.log(dataRes);
}
Executed this code works and the response will be displayed as expected.
If I execute this in a mocha test the request is not executed:
describe('api', function() {
it('should load a user', function() {
assert.doesNotThrow(function() {
doRequest(options, myCallback, function(err) {
if (err) throw err;
done();
});
});
assert.equal(res, '{Object ... }');
});
});
The Problem is, that no code after:
var req = protocol.request(options, function(res) {
is executed not even a simple console.log.
Can anybody help?
You have to specify the callback done as the argument to the function which is provided to mocha - in this case the it() function. Like so:
describe('api', function() {
it('should load a user', function(done) { // added "done" as parameter
assert.doesNotThrow(function() {
doRequest(options, function(res) {
assert.equal(res, '{Object ... }'); // will not fail assert.doesNotThrow
done(); // call "done()" the parameter
}, function(err) {
if (err) throw err; // will fail the assert.doesNotThrow
done(); // call "done()" the parameter
});
});
});
});
Also, the signature of doRequest(options, callback) specifies two arguments though when you call it in the test you provide three.
Mocha probably couldn't find the method doRequest(arg1,arg2,arg3).
Did it not provide some error output? Maybe you can change the mocha options to get more information.
EDIT :
andho is right, the second assert would be called in parallel to assert.doesNotThrow while it should only be called in the success callback.
I have fixed the example code.
EDIT 2:
Or, to simplify the error handling (see Dan M.'s comment):
describe('api', function() {
it('should load a user', function(done) { // added "done" as parameter
assert.doesNotThrow(function() {
doRequest(options, function(res) {
assert.equal(res, '{Object ... }'); // will not fail assert.doesNotThrow
done(); // call "done()" the parameter
}, done);
});
});
});
If you have an asynchronous function that does not support callbacks, or if you think using unnecessary callbacks is... unnecessary, then you can also just turn the test into an async test.
instead of:
it('should be able to do something', function () {});
simply do:
it('should be able to do something', async function () {});
^^^^^
Now you can await async functions:
it('should be able to do something', async function () {
this.timeout(40000);
var result = await someComplexFunction();
assert.isBelow(result, 3);
});
I've done a very similar test in my project for an http client. I paste the code here and hope is useful.
Here is the client (my nodejs server use express and I use promise for error handling):
var http = require('http');
var querystring = require('querystring');
module.exports = {
get: function(action, params, res, callback) {
doPromiseRequest(action, querystring.stringify(params), callback, 'GET', 'application/json')
.then((response) => callback(response))
.catch((error) => {
res.status(500);
res.render('error', {layout: false, message: error.message, code: 500});
});
},
}
function doPromiseRequest(action, params, callback, method, contentType) {
var options = {
hostname: 'localhost',
port: 3000,
path: '/api/v1/' + action.toString(),
method: method,
headers: {
'Content-Type': contentType,
'Content-Length': Buffer.byteLength(params)
}
};
return new Promise( (resolve, reject) => {
var req = http.request(options,
function(response) {
response.setEncoding('utf8');
var data = '';
response.on('data', function(chunk) {
data += chunk;
});
response.on('end', function() {
var parsedResponse;
try {
parsedResponse = JSON.parse(data);
} catch(err) {
reject({message: `Invalid response from hurricane for ${action}`});
return;
}
if (parsedResponse.error)
reject(parsedResponse.error);
else
resolve(parsedResponse);
});
response.on('error', function(err){
console.log(err.message);
reject(err);
});
});
req.on('error', function(err) {
console.log(err);
reject({message: err.message});
});
req.write(params);
req.end();
});
}
And here is the test:
var http = require('http');
var expect = require('chai').expect;
var sinon = require('sinon');
var PassThrough = require('stream').PassThrough;
describe('Hurricane Client tests', function() {
before(function() {
this.request = sinon.stub(http, 'request');
});
after(function() {
http.request.restore();
});
it('should convert get result to object', function(done) {
var expected = { hello: 'world' };
var response = new PassThrough();
response.statusCode = 200;
response.headers = {}
response.write(JSON.stringify(expected));
response.end();
var request = new PassThrough();
this.request.callsArgWith(1, response).returns(request);
client.get('any', {}, null, function(result) {
expect(result).to.eql(expected);
done();
});
});
});