How to change NodeJS Request Stream response - node.js

I'm somewhat new to NodeJS, and current I used Express and Request ( https://github.com/request/request ) to forward my app request to REST api server, current my code shown below:
app.use('/rest/*', function(req, res) {
req.pipe(request('http://ipaddress/api')).pipe(res);
});
this code works when the REST API server is OK, but if the rest api server goes down, my nodejs app also goes down, because request stream will fail and the error is not caught by my app.
I checked the Request github page, it provides one way to handle the stream error, like
app.use('/rest/*', function(req, res) {
req.pipe(request('http://ipaddress/api').on('error', function(err) {
console.log(err);
})).pipe(res);
});
this can only log the error and prevent my NodeJS app crashing, but I want to change the response when error occurred so that the changed response can be piped to final one, for example, what I want to do in pseudocode:
app.use('/rest/*', function(req, res) {
req.pipe(request('http://ipaddress/api').on('error', function(err) {
console.log(err);
// what I want to do in pseudocode
response.statusCode = 500;
response.json = {
reason: err.errno
};
})).pipe(res);
});
Are there any ways to solve my problems? Thanks for any ideas!

Untested but could you pass the error back to middleware to handle the reponse?
app.use('/rest/*', function(req, res, next) {
req.pipe(request('http://ipaddress/api').on('error', function(err) {
return next(err)
})).pipe(res);
});
Handled like so
// Exception handling
app.use(function (error, req, res, next) {
console.log(error);
res.status(500).send(JSON.stringify(error));
next();
});

Related

Problem with handling errors in Express framework

I am currently working on node.js + express + mongoDB project. I am trying to handle error that occurs when data cannot be received from database. I am simulating this by terminating mongod process in console and calling .get in Postman. Sadly instead of getting an error in Postman I only get Unhandled Promise Rejection in console. I read a lot of posts about error handling and implemented it according to this guide: https://expressjs.com/en/guide/error-handling.html. I would be grateful for any idea of how can I fix this.
The code:
Printing all courses:
router.get("/", async (req, res, next) => {
try {
const courses = await Course.find().sort("dishName");
res.send(courses);
} catch (ex) {
next(ex);
}
});
error.js:
module.exports = function (err, res, req, next) {
res.status(500).send(`500 Error`);
};
index.js
const error = require(`./middleware/error`);
app.use(error);
app.use(error) is placed as the last app.use
There is a minor mistake in your code. The order of the req and res parameters in the error handler function should not be changed.
// Error.js
module.exports = function (err, req, res, next) {
res.status(500).send(`500 Error`);
};

Supress logging to console on next(err) method in express

app.get('/test', (req, res, next) => {
const err = new Error('Test');
next(err);
});
express will log the error and stacktrace to the console. Is there a way that I can suppress the logging?
If you put an error handler middleware in your Express implementation to handle the next(err) call like this:
// defined as the last route
app.use(function (err, req, res, next) {
res.status(500).send('Something broke!')
});
then, Express won't log any error and you can control what response is sent for the error.
I'd suggest reading this page on Express error handling: https://expressjs.com/en/guide/error-handling.html.
If you look in the express code where this logging comes from, it comes from this code:
function logerror(err) {
/* istanbul ignore next */
if (this.get('env') !== 'test') console.error(err.stack || err.toString());
}
which curiously enough shows that if you do this:
app.set('env', 'test');
or you set NODE_ENV=test in the environment before launching your server, then it will skip the error logging too. But, it's much better to just control things with your own error handler as I show about where you can also control what type of response is sent.

Log response status in sails

I'm trying to log every request made to my sails application, but I can't find a way to log the response associated with a request.
I added this custom middleware in the config/http.js file :
myRequestLogger: function (req, res, next) {
req.on("end", function(){
sails.log(res.statusCode);
});
return next();
}
But it doesn't work properly, I can get the 200 codes, buta res.forbidden or res.notFound response is not logged. Any idea about how I could handle that ?
Thank you
You can override that in api/responses itself. Here is simplified override:
// api/responses/forbidden.js
module.exports = function(err, viewOrRedirect) {
// ... Sails logic
this.req._sails.log.verbose();
}
But, if you expect that your middleware above can do this, you're wrong. Your middleware should looks similar to this:
myRequestLogger: function(req, res, next) {
req._sails.log.verbose('YOUR LOG');
return next();
}
Ok, I have found the answer by reading this stackoverflow post : https://stackoverflow.com/a/11841877/2700309
Apparently there is a 'finish' event emitted just before the response is send to the client. So the right code would be :
myRequestLogger: function (req, res, next) {
res.on("finish", function(){
sails.log(res.statusCode);
});
return next();
}
And this seems to work!

How to handle 403 HTTP error in restify?

I've been trying to handle HTTP error in restify. these are the codes i've been trying so far :
function send403(req, res, err, cb) {
console.log('Forbidden');
res.end();
}
And then i use that function in ForbiddenError event :
server.on('ForbiddenError', send403);
I'm expecting that function to be executed everytime server receive a request without authorization header
server.get('/resource', function (req, res, next) {
if(typeof req.headers['authorization'] === 'undefined') {
return next(new restify.ForbiddenError());
}
else {
// HTTP 200
}
});
Everytime i try to access the url i keep getting that default restify JSON message.
FYI i've tried the same method for 404 error and it works
server.on('NotFound', send404);
Everytime i try to send a request to a non-existing url, the send404 function will be executed.
I think this might be what you are looking for. I noticed that in the "server.on" statement restify doesn't want the "Error" part. The following is a complete working example.
'use strict';
var restify = require('restify');
var server = restify.createServer();
server.on('Forbidden', send403);
server.get('/resource', function(req, res, next){
if(typeof req.headers['authorization'] === 'undefined') {
next(new restify.ForbiddenError());
}
else {
// HTTP 200
}
});
function send403(req, res, err, cb){
console.log('Log something here');
return cb();
}
server.listen(9000);
console.log('listening on port 9000');

How to write to response from HTTP Client Node.JS

I have the following...
var request = require('request');
exports.list = function(req, res){
res.send("Listing");
};
exports.get = function(req, res){
request.get("<URL>", function (err, res, body) {
if (!err) {
res.send(body,"utf8");
}
});
};
This fails with the following....
TypeError: Object #<IncomingMessage> has no method 'send'
How do I do this?
UPDATE tried to use write instead of send but...
/Users/me/Development/htp/routes/property.js:9
res.setHeader('Content-Type', 'text/html');
^
TypeError: Object #<IncomingMessage> has no method 'setHeader'
Also writing out to the console instead works fine.
Problem was with scope of variables, my response output was the same name as the response object I got back in my callback. Changing this around (resp vs res) made it work....
exports.get = function(req, res){
request.get("<url>", function (err, resp, body) {
if (!err) {
res.send(body);
}
});
};
What you are trying to do, is to make Request > Response server. But you are using Request module, that allows to get stuff rather than respond.
What you need is http or better get express.js and use it, as it is straight forward and well popular web framework for exactly what you need.
I wasn't aware OP is using Express. You will encounter a similar error if you attempt to use req.send with the vanilla HTTP module instead of Express.
var http = require('http');
function requestHandler(req, res){
//res.send(200, '<html></html>'); // not a valid method without express
res.setHeader('Content-Type', 'text/html');
res.writeHead(200);
res.end('<html><body>foo bar</body></html>');
};
http.createServer(handler).listen(3000);

Resources