how to catch a server response? - node.js

There is a client wich is sending requests to my webserver. This Server should answer with data or an specific code, for example 117 (yes this a halo reference :D) Now I need access to the responded data or code. How could I realize this? I found nothing similar here at stackoverflow, may you can help.
Client example:
function sendRequest() {
var options = {
host: 'localhost',
port: 1309,
path: '/examplePath?param='+param,
param: "example"
};
http.get(options, function(resp){
resp.on('data', function(chunk){
console.log("chunk :",chunk);
});
}).on("error", function(err){
console.log("Error: " + err.message);
});
}
Answering Server:
function examplePathFunction(req,res) {
if(condition) {
//TODO Server must answer with data
} elseĀ {
//TODO Server must answer with status 117
}
}
Would : res.end(date/code); solve my problem? And how do I catch this response ?

I think you're looking for:
function examplePathFunction(req, res, next) {
if(req.body.data) {
res.status(200).send({ data: req.body.data });
return next();
} else {
res.status(117);
return next();
}
}
Though if you're trying to send data through params, look there rather than the request body.
Read more about the Express API: http://expressjs.com/en/api.html#req

Related

Get method - Why can't I return the values from an Oracle view?

I searched for a good example of Node+Express+Oracle. I need to read values from an Oracle view to create the response to a GET operation.
Most examples does not use "Express" (my choice of framework) and simply log the database information. Here are some of the best I found : from Express, from Oracle 1, from Oracle 2
Here is the one I preferred to base my code on. I like it because it includes Express, and actual manipulation of the response data. Sadly, it still does not work for me. And I am wondering what the issue is.
I think I understand the asynchronous nature of the JavaScript language (ie: callbacks), and I am beginning to suspect my problem might be tied to : A stupid variable name snafu, My version of Oracle (12c) or the fact that the source is a view (replicated from another schema).
I tried the following code in many other forms (including async functions), and also tried to switch from node 10 to 11... no changes.
Any help would be welcomed.
As of now, the code "works", in the sense that the row data from the database is printed on screen, but the response in Postman (my test tool) is empty, with no http error code... just like the connection would have been cut before replying.
Note the commented, misplaced response code, that returns a response if uncommented (and then crashes the program since the header is written twice).
Here is the code.
It is based on this project/file (and simplifed):
var express = require('express');
var oracledb = require('oracledb');
var app = express();
var connAttrs = {
"user": "user",
"password": "pass",
"connectString": "some_host/SCHEMANAME"
}
// Http Method: GET
// URI : /myObj
app.get('/myObj', function (req, res) {
"use strict";
oracledb.getConnection(connAttrs, function (err, connection) {
if (err) {
// Error connecting to DB
res.set('Content-Type', 'application/json');
res.status(500).send(JSON.stringify({
status: 500,
message: "Error connecting to DB",
detailed_message: err.message
}));
return;
}
// THIS works if uncommented. This is obviously the wrong place to put this.
//res.contentType('application/json').status(200);
//res.send("Test.1.2");
connection.execute("SELECT * FROM SCHEMA.SOMEVIEW", {}, {
outFormat: oracledb.OBJECT // Return the result as Object
}, function (err, result) {
if (err) {
res.set('Content-Type', 'application/json');
res.status(500).send(JSON.stringify({
status: 500,
message: "Error getting the user profile",
detailed_message: err.message
}));
} else {
//log first row... THIS WORKS !
console.log(result.rows[0]);
//This does not work, like if "res" could not be touched here !!!
res.contentType('application/json').status(200);
res.send(JSON.stringify(result.rows[0]));
}
// Release the connection
connection.release(
function (err) {
if (err) {
console.error(err.message);
} else {
console.log("GET /myObj: Connection released");
}
});
});
});
});
var server = app.listen(3000, function () {
"use strict";
var host = server.address().address,
port = server.address().port;
console.log(' Server is listening at http://%s:%s', host, port);
});
Here is a representation of the console:
{ field1: 'some data',
field2: 'some more data' }
GET /myObj : Connection released
And here is the behaviour in postman:
ARGGG ! It was a simple timeout ! Postman DOES mention it as a possibility (see image), but I would like the program to make it flash it bright letters !!!
Closing the question. Sorry for the disturbance.

How to send response back to client using socket.io?

I have socket.emit call from client to server in response i want to have filename to the client that is not happening with below code not sure what is implemented wrong any idea, I do not see any error. How can i get response fro server using socket.emit ?
client.js
socket.emit('startRecording',function (response) {
console.log('start recording emit response',response);
});
server.js
socket.on('startRecording',function () {
var response;
logsRecording(function (filename) {
response = filename;
return response;
//socket.emit('filename',filename);
});
To acknowledge the message, your handler for the startRecording event needs to accept an acknowledgement callback as a parameter. You can then call that with your desired data. See Sending and getting data (acknowledgements)
socket.on('startRecording',function (socket, ackFn) {
var response;
logsRecording(function (filename) {
ackFn(filename);
});
});
Alternatively, you could add a listener for that filename event you have commented out, in the client.js:
socket.emit('startRecording');
socket.on('filename', function(filename) {
console.log('Filename received: ' + filename);
});
It might be helpful to run through Get Started: Chat application starting at the heading "Integrating Socket.IO" to get a more general understanding of Websockets.
Your server code should look like this:
socket.on('startRecording',function (callbackFn) {
var response;
logsRecording(function (filename) {
callbackFn(filename);
});
If you want to pass in data from your client:
socket.emit('startRecording', {someData: 'value'}, function (response) {
then server will be :
socket.on('startRecording',function (dataFromClient, callbackFn) {
Thank you for this helpfull hint
Here an 2020 "call" example call possible to use with moleculer microservices with four arguments:
The server responds in the callback function with two arguments err and res for the angular promise.
Angular 9 socket io
protected call(method: string, param?: any) {
try {
return new Promise((resolve, reject) => {
this.socket.emit("call", method, param, (err: any, res: unknown) => {
console.log(res);
if (err) { return reject(err); }
return resolve(res);
});
});
} catch (err) {
console.error(err);
}
}
Socket IO server response
socket.on('call', function(method, param, callbackFn){ // call method, param,
console.log(param);
switch (method) {
case "test":
console.log("test detected");
callbackFn(null , {name:"test",email:"test"});
break;
}
});

Wait for JSON response data from POST request in nodejs (mocha test)

I'm aware that there are several questions related to mine, but I didn't find any of them useful:
this one doesn't apply to my case, I'm actually getting the answer, it's the contents that I can't get.
on this one, on the other hand, the problem is a wrong handling of an asynchronous call, which is not my case
there, well, I really didn't fully understand this question
And so on...
Then, I think this is a legitimate question. I'm actually performing some encryption in my server (express routing in node) through a post request:
app.post('/encrypt', encrypt);
Encrypt is doing:
function encrypt(req,res) {
if(req.body.key && req.body.message) {
var encryptedMessage = Encrypter.encrypt(req.body.key,req.body.message);
return res.status(200).json({ message: encryptedMessage });
}
res.status(409).json({ message: 'the message could not be encrypted, no key found' });
}
}
So, I tested this via console.log, and it's working. When the server receives the request, the encrypted message is being generated.
At the same time, I'm testing my thing with mocha and I'm doing it like so:
describe('# Here is where the fun starts ', function () {
/**
* Start and stop the server
*/
before(function () {
server.listen(port);
});
after(function () {
server.close();
});
it('Requesting an encrypted message', function(done) {
var postData = querystring.stringify({
key : key,
message : message
});
var options = {
hostname: hostname,
port: port,
path: '/encrypt',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': postData.length
}
};
var req = http.request(options, function(res) {
res.statusCode.should.equal(200);
var encryptedMessage = res.message;
encryptedMessage.should.not.equal(message);
done();
});
req.on('error', function(e) {
//I'm aware should.fail doesn't work like this
should.fail('problem with request: ' + e.message);
});
req.write(postData);
req.end();
});
});
So, whenever I execute the tests, it fails with Uncaught TypeError: Cannot read property 'should' of undefined because res.message does not exist.
None of the res.on (data, end, events is working, so I suppose the data should be available from there. First I had this:
var req = http.request(options, function(res) {
res.statusCode.should.equal(200);
var encryptedMessage;
res.on('data', function (chunk) {
console.log('BODY: ' + chunk);
encryptedMessage = chunk.message;
});
encryptedMessage.should.not.equal(message);
done();
});
But res.on was never accessed (the console.log didn't show anything). I'm therefore a bit stuck here. I'm surely doing some basic stuff wrong, but I don't have a clue, and the many questions I found doesn't seem to apply to my case.
Weird enough, if I launch a test server and then I curl it
curl --data "key=secret&message=veryimportantstuffiabsolutellyneedtoprotect" localhost:2409/encrypt
Curl justs waits ad aeternam.
Actually I was doing it properly at the beginning, and the problem was indeed the same than in the second question I mentionned I was actually "clearing" my context with done() before the post data arrived. The solution is:
var req = http.request(options, function(res) {
res.statusCode.should.equal(200);
res.on('data', function(data) {
encryptedMessage = JSON.parse(data).message;
encryptedMessage.should.not.equal(message);
done();
});
});
In such a way that done() is only called when the data has been threated. Otherwise, mocha will not wait for the answer.

Node.js - How to get my external IP address in node.js app?

I'm using node.js and I need to get my external IP address, provided by my ISP.
Is there a way to achieve this without using a service like http://myexternalip.com/raw ?
Thanks.
Can do the same as what they do in Python to get external IP, connect to some website and get your details from the socket connection:
const net = require('net');
const client = net.connect({port: 80, host:"google.com"}, () => {
console.log('MyIP='+client.localAddress);
console.log('MyPORT='+client.localPort);
});
*Unfortunately cannot find the original Python Example anymore as reference..
Update 2019:
Using built-in http library and public API from https://whatismyipaddress.com/api
const http = require('http');
var options = {
host: 'ipv4bot.whatismyipaddress.com',
port: 80,
path: '/'
};
http.get(options, function(res) {
console.log("status: " + res.statusCode);
res.on("data", function(chunk) {
console.log("BODY: " + chunk);
});
}).on('error', function(e) {
console.log("error: " + e.message);
});
Tested with Node.js v0.10.48 on Amazon AWS server
--
Update 2021
ipv4bot is closed, here is another public API:
var http = require('http');
http.get({'host': 'api.ipify.org', 'port': 80, 'path': '/'}, function(resp) {
resp.on('data', function(ip) {
console.log("My public IP address is: " + ip);
});
});
--
Update 2022
ChatGPT wrote longer example using ipify with json: *Yes, i've tested it.
https://gist.github.com/unitycoder/745a58d562180994a3025afcb84c1753
More info https://www.ipify.org/
npm install --save public-ip from here.
Then
publicIp.v4().then(ip => {
console.log("your public ip address", ip);
});
And if you want the local machine ip you can use this.
var ip = require("ip");
var a = ip.address();
console.log("private ip address", a);
Use my externalip package on GitHub
externalip(function (err, ip) {
console.log(ip); // => 8.8.8.8
});
Edit: This was written back in 2013... The site is gone. I'm leaving the example request code for now unless anyone complains but go for the accepted answer.
http://fugal.net/ip.cgi was similar to that one.
or you can
require('http').request({
hostname: 'fugal.net',
path: '/ip.cgi',
agent: false
}, function(res) {
if(res.statusCode != 200) {
throw new Error('non-OK status: ' + res.statusCode);
}
res.setEncoding('utf-8');
var ipAddress = '';
res.on('data', function(chunk) { ipAddress += chunk; });
res.on('end', function() {
// ipAddress contains the external IP address
});
}).on('error', function(err) {
throw err;
}).end();
Ref: http://www.nodejs.org/api/http.html#http_http_request_options_callback
this should work well without any external dependencies (with the exception of ipify.org):
var https = require('https');
var callback = function(err, ip){
if(err){
return console.log(err);
}
console.log('Our public IP is', ip);
// do something here with the IP address
};
https.get({
host: 'api.ipify.org',
}, function(response) {
var ip = '';
response.on('data', function(d) {
ip += d;
});
response.on('end', function() {
if(ip){
callback(null, ip);
} else {
callback('could not get public ip address :(');
}
});
});
You could also use https://httpbin.org
GET https://httpbin.org/ip
Simply use superagent
var superagent = require('superagent');
var getip = function () {
superagent
.get('http://ip.cn/')
.set('User-Agent', 'curl/7.37.1')
.end(function (err, res) {
if (err) {
console.log(err);
}
var ip = res.text.match(/\d+\.\d+\.\d+\.\d+/)[0];
console.log(ip)
// Here is the result
});
};
Another little node module is ext-ip. The difference is, that you can use different response options, matching your coding style. It's ready to use out of the box ...
Promise
let extIP = require('ext-ip')();
extIP.get().then(ip => {
console.log(ip);
})
.catch(err => {
console.error(err);
});
Events
let extIP = require('ext-ip')();
extIP.on("ip", ip => {
console.log(ip);
});
extIP.on("err", err => {
console.error(err);
});
extIP();
Callback
let extIP = require('ext-ip')();
extIP((err, ip) => {
if( err ){
throw err;
}
console.log(ip);
});
The simplest answer, based on experience is that you can't get your external IP in most cases without using an external service, since you'll typically be behind a NAT or shielded by a firewall. I say in most cases, since there may be situations where you can get it from your router, but it is too case specific to provide a general answer.
What you want is simply to choose your favourite http client in NodeJS and find a maintained server that simply responds with the IP address in the body. You can also use a package, but you should see if it is still using a maintained remote server.
While there are plenty of examples already, here is one that first tries IPv6 and then falls back to IPv4. It leverages axios, since that is what I am comfortable with. Also, unless the optional parameter debug is set to true, the result is either a value or undefined.
const axios = require('axios');
// replace these URLs with whatever is good for you
const remoteIPv4Url = 'http://ipv4bot.whatismyipaddress.com/';
const remoteIPv6Url = 'http://ipv6bot.whatismyipaddress.com/';
// Try getting an external IPv4 address.
async function getExternalIPv4(debug = false) {
try {
const response = await axios.get(remoteIPv4Url);
if (response && response.data) {
return response.data;
}
} catch (error) {
if (debug) {
console.log(error);
}
}
return undefined;
}
// Try getting an external IPv6 address.
async function getExternalIPv6(debug = false) {
try {
const response = await axios.get(remoteIPv6Url);
if (response && response.data) {
return response.data;
}
} catch (error) {
if (debug) {
console.log(error);
}
}
return undefined;
}
async function getExternalIP(debug = false) {
let address;
// Try IPv6 and then IPv4
address = await getExternalIPv6(debug);
if (!address) {
address = await getExternalIPv4(debug);
}
return address;
}
module.exports { getExternalIP, getExternalIPv4, getExternalIPv6 }
Feel free to suggest improvements.
You may use the request-ip package:
const requestIp = require('request-ip');
// inside middleware handler
const ipMiddleware = function(req, res, next) {
const clientIp = requestIp.getClientIp(req);
next();
};
My shameless plug: canihazip (Disclosure: I'm the author of module, but not of the main page.)
It can be required as a module, exposing a single function that can optionally be passed a callback function an it will return a promise.
It can be also be installed globally and used as CLI.
You could very easily use an api solution for retrieving the external IP!
I made a ip tracker site made for this kinda thing a few days ago!
Here is a snippit of code you could use to get IP!
async function getIp(cb) {
let output = null;
let promise = new Promise(resolve => {
let http = new XMLHttpRequest();
http.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
output = this.responseText;
resolve("done");
}
}
http.open("GET", "https://iptrackerz.herokuapp.com/ip", true);
http.send();
});
await promise;
if (cb != undefined) {
cb(JSON.parse(output)["ip"]);
} else {
return JSON.parse(output)["ip"];
}
}
Ok, now you have the function getIp()!
The way I coded it allows you to do 2 different ways of invoking it!
Here they are.
Asynchronous
async function printIP() {
let ip = await getIp();
document.write("Your IP is " + ip);
};
printIP();
Callback
getIp(ip => {
document.write("Your IP is " + ip);
});
I was looking for a solution not relying to other's libraries/ resources,
and found this as acceptable alternative:
Just a GET request to external server ( under my control ),
where I read req.headers['x-forwarded-for'] and serve it back to my client.
node.js has a lot of great built in modules you can use without including any external dependencies. you can make this file.
WhatsMyIpAddress.js
const http = require('http');
function WhatsMyIpAddress(callback) {
const options = {
host: 'ipv4bot.whatismyipaddress.com',
port: 80,
path: '/'
};
http.get(options, res => {
res.setEncoding('utf8');
res.on("data", chunk => callback(chunk, null));
}).on('error', err => callback(null, err.message));
}
module.exports = WhatsMyIpAddress;
Then call it in your main.js like this.
main.js
const WhatsMyIpAddress = require('./src/WhatsMyIpAddress');
WhatsMyIpAddress((data,err) => {
console.log('results:', data, err);
});
You can use nurl library command ippublic to get this. (disclosure: I made nurl)
> npm install nurl-cli -g
> ippublic;
// 50.240.33.6

node.js error when an http.request is issued to a server that is not responding

I am writing a node.js server which acts as an API between a client and a java server that is one step downstream of the node.js API. The API accepts incoming HTML requests from the client, reformats them, and sends them out to the java server, which returns its answer to the node.js API, which returns it back to the client. This all works beautifully, except for when the server is down. i need to catch that event, just like I can catch a 502 or a 302... here is my code:
async.waterfall(
[
function(callback){
var options = { host: 'localhost', port: '8080',
path: '/javaServerWork/' + req.query.foo + '?toDo=' + req.query.bar,
method: 'GET',
headers: { accept: 'application/json' }
};
http.request(options, function(response){
response.on('error', function(exception) { Console.log("error here"); }
if(response.statusCode == '200'){ callback(null, response); }
else if (response.statusCode == '502') { res.send('502'); }
else { res.send('not 200 and not 502'); }
}).end();
},
function(response){
var javaResponse = '';
response.on('error', function(exception){ Console.log("error here");});
response.on('data', function (chunk){ javaResponse += chunk; });
response.on('end', function(){
res.send(javaResponse);
})
}
]
);
when i start up this node server and issue a request to the node.js server which then attempts to reach the java server, node.js crashes and i get the following error in my console:
events.js:69
throw arguments[1]; // Unhandled 'error' event
^
Error: connect ECONNREFUSED
at errnoException (net.js:846:11)
at Object.afterConnect [as oncomplete] (net.js:837:19)
All I need to do is catch the "no response" when the java server is down, so that i can execute another function or simply return that fact back to the client, of course, without node crashing! This may be very simple, but i have found nothing that works. I have tried process.on('uncaughtException'), I have tried (as in the code) response.on('error').
I am new to node and can't see where the problem is... Any help greatly appreciated!
Did you try
http.request(options, function(response){
response.on('error', function(exception) { Console.log("error here"); }
if(response.statusCode == '200'){ callback(null, response); }
else if (response.statusCode == '502') { res.send('502'); }
else { res.send('not 200 and not 502'); }
}).on('error', function(e) {
console.log("handle error here");
}).end();
Sounds like the error is being thrown on the request object that http.request returns, not on the response object
(http://nodejs.org/api/http.html#http_http_request_options_callback)

Resources