I'm building an express app, a basic twitter interface.
I want to add an error page to the application, so that if anything goes wrong with the routes the user will see a friendly message rendered, instead of the default error code.
Here is a snippet of my code:
//Tell app to render template
app.get('/', function(req, res){
if(!error){
res.render('index', {
myName: myName,
profileImage: profileImage,
screenName: screenName,
followerCount: followerCount,
dateTweeted: dateTweeted,
tweetContent: tweetContent,
noOfRetweets: noOfRetweets,
noOfLikes: noOfLikes,
});
}
});
Why can't I just do this?
else{
res.send('sorry, bro, page not found!);
}
Or do I need to do something with passing the error to the 'next’ handler? I can't get my head around how that works.
Would really appreciate some help please!
Your question is not very specific but I assume you will get some errors during manipulation.
Then you can send type of error like this after getting error
//Tell app to render template
app.get('/', function(req, res) {
if ("not error") {
//You can do whatever you want
res.status(200).send({message:"Success message"})
}else{//If error you can choose your error code with relevant message
res.status(400).send({message:"Bad request error"});
//OR
res.status(404).send({message:"Not found error"});
//OR
res.status(401).send({message:"Unauthorization error"});
//OR
res.send(500).send({message:"Any server side erorr"});
}
});
You can build a custom middlewarethat does this for you...
function errorMiddleware(req, res, next) {
// implement some logic, do your check...
let thereAreErrors = /* ? */ false;
if(!thereAreErrors) {
return next();
}
return res.status(400).end();
}
function indexRouteCtrl(req, res) {
return res.render('index');
}
app.get('/'/, errorMiddleware, indexRouteCtrl);
Related
I send a POST request from front end and I declare my route like below
router.post('/login', function(req, res, next) {
});
My app crash and I got Error: Can't set headers after they are sent.
Here is my full code for route : http://pastebin.com/EnfXu8Vm
You cannot send twice the reply to the same request.
So the code here:
if(result){
res.json({msg:0})
}
res.json({msg:1})
You can probably want to do
if (result) {
res.json({msg:0});
} else {
res.json({msg:1});
}
or, to be more similar to your original code (so without else):
if (result) {
return res.json({msg:0});
}
res.json({msg:1});
In app.js, I have
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
so if I request some not exist url like http://localhost/notfound, above code will execute.
In exist url like http://localhost/posts/:postId, I would like to throw 404 error when access some not exist postId or deleted postId.
Posts.findOne({_id: req.params.id, deleted: false}).exec()
.then(function(post) {
if(!post) {
// How to throw a 404 error, so code can jump to above 404 catch?
}
In Express, a 404 isn't classed as an 'error', so to speak - the reasoning behind this is that a 404 isn't usually a sign that's something's gone wrong, it's just that the server couldn't find anything. Your best bet is to explicitly send a 404 in your route handler:
Posts.findOne({_id: req.params.id, deleted: false}).exec()
.then(function(post) {
if(!post) {
res.status(404).send("Not found.");
}
Or alternatively, if this feels like too much repeated code, you could always pull that code out into a function:
function notFound(res) {
res.status(404).send("Not found.");
}
Posts.findOne({_id: req.params.id, deleted: false}).exec()
.then(function(post) {
if(!post) {
notFound(res);
}
I wouldn't recommend using a middleware in this situation solely because I feel like it makes the code less clear - the 404 is the direct result of the database code not finding anything, so it makes sense to have the response in the route handler.
I have the same app.js structure, and I solved this problem in this way in the route handler:
router.get('/something/:postId', function(req, res, next){
// ...
if (!post){
next();
return;
}
res.send('Post exists!'); // display post somehow
});
The next() function will call the next middleware which is the error404 handler if it is right after your routes in the app.js.
You can use this and the end of your routers.
app.use('/', my_router);
....
app.use('/', my_router);
app.use(function(req, res, next) {
res.status(404).render('error/404.html');
});
you're probably looking for something like https://github.com/expressjs/api-error-handler
or just https://github.com/jshttp/http-errors
Even though 404 pages are not considered an error in Express as written here, its really damn handy if you DO handle them like so. For instance when you are developing an API that wants consistent JSON output. The following code should help you with that:
Define a helper function abort to create status errors that can be easily used in your code to pass to the next function:
// Use the `statuses` package which is also a dependency of Express.
const status = require('statuses');
const abort = (code) => {
const err = new Error(status[code]);
const err.status = code;
return err;
};
Define the catch-all middleware for 404 pages which should be defined at the bottom of your stack (after all routes have been added). This forwards the 404 as an error:
app.use((req, res, next) => {
next(abort(404));
});
Lastly, the final error handler will now consistently send all errors in JSON format:
app.use((err, req, res, next) => {
if(!res.headersSent) {
// You can define production mode here so that the stack trace will not be sent.
const isProd = false;
res.status(err.status || 500).json({
error: err.toString(),
...(!isProd && {stack: err.stack.split('\n').map(i => i.trim())}),
});
}
next(err);
});
I have registration form and posting the values to register function where it will validate form values with node-validator.
But, when I tried with node-validator, it keeps getting error as
TypeError: Object # has no method 'onValidationError'. The validator already installed in my app.
In app.js
app.post('/register', test.register);
In test.js
var check = require('validator').check,
sanitize = require('validator').sanitize;
exports.register = function(req, res){
var errors = [];
req.onValidationError(function(msg) {
//res.render('signup', { error: msg });
errors.push(msg);
});
req.check(req.body.email, 'Please enter a valid email').len(6,64).isEmail();
req.check(req.body.username, "Username can't be empty!").isNull();
if (errors.length)
return res.render(
'register', { regErr: errors.join('\n') }
);
}
How to correct this error?
You are using node-validator . You should be using express-validator for onValidationError
From node-validator page you can see it:
If you are using the express.js framework you can use the
express-validator middleware to seamlessly integrate node-validator.
Example http://localhost:8080/?zip=12345&foo=1&textarea=large_string
get('/', function (req, res) {
req.onValidationError(function (msg) {
//Redirect the user with error 'msg'
});
Additional Note:
The order of app.use is also important. Try to move app.use(expressValidator); up of app.use(app.router);. You can view the order of app.use in https://github.com/justin-john/node-user-management/blob/master/app.js#L17-L18.
I'm working with Node.js, express, mongodb, and got stuck on this data passing between frontend and backend.
Note: code below is middleware code for front- and backend communication
Here I successfully get the input value from the frontend by using req.body.nr
exports.find_user_post = function(req, res) {
member = new memberModel();
member.desc = req.body.nr;
console.log(req.body.nr);
member.save(function (err) {
res.render('user.jade', );
});
};
Here is the problem, I need to use the input value I got to find the correct data from my database(mongodb in the backend) and push out to the frontend.
My data structure {desc : ''}, the desc is correspond to the input value so it should look something like this {desc: req.body.nr} which is probably incorrect code here?
exports.user = function(req, res){
memberModel.find({desc: req.body.nr}, function(err, docs){
res.render('user.jade', { members: docs });
});
};
Would love to have some help.
Thanks, in advance!
Have a look at this great tutorial from howtonode.org.
Because as you can see he uses a prototype and a function callback:
in articleprovider-mongodb.js
ArticleProvider.prototype.findAll = function(callback) {
this.getCollection(function(error, article_collection) {
if( error ) callback(error)
else {
article_collection.find().toArray(function(error, results) {
if( error ) callback(error)
else callback(null, results)
});
}
});
};
exports.ArticleProvider = ArticleProvider;
in app.js
app.get('/', function(req, res){
articleProvider.findAll( function(error,docs){
res.render('index.jade', {
locals: {
title: 'Blog',
articles:docs
}
});
})
});
Also make sure you have some error checking from the user input as well as from the anybody sending data to the node.js server.
PS: note that the node, express and mongo driver used in the tutorial are a bit older.
I am beginning to work with Express JS and have run into an issue. I can't seem to figure out the proper way to handle errors.
For example, I have a web services API that serves an object called "event". I'd like to return a simple string of "cannot find event" when a user submits an event id that isn't found. Here is how I'm currently structuring my code:
app.get('/event/:id', function(req, res, next) {
if (req.params.id != 1) {
next(new Error('cannot find event ' + req.params.id));
}
req.send('event found!');
});
When I submit an id other than 1, Node crashes with the following output:
http.js:527
throw new Error("Can't set headers after they are sent.");
^
Error: Can't set headers after they are sent.
at ServerResponse.<anonymous> (http.js:527:11)
at ServerResponse.setHeader (/usr/local/kayak/node_modules/express/node_modules/connect/lib/patch.js:62:20)
at /usr/local/kayak/node_modules/express/node_modules/connect/lib/middleware/errorHandler.js:72:19
at [object Object].<anonymous> (fs.js:107:5)
at [object Object].emit (events.js:61:17)
at afterRead (fs.js:878:12)
at wrapper (fs.js:245:17)
From what I can tell by using the node.js debugger, execution of the block of code continues after next() is called, meaning that req.send('event found!') tries to run. I don't want this to happen.
The only workaround that I've found is to simply throw a new Error() instead of "next-ing" it, but this results in a default Express HTML error page being generated. I'd like a little more control than that.
I have taken the time to read over the error handling section of the Express documentation, but I couldn't make sense of it.
You'll want to check out Express Error Handling. From there:
app.param('userId', function(req, res, next, id) {
User.get(id, function(err, user) {
if (err) return next(err);
if (!user) return next(new Error('failed to find user'));
req.user = user;
next();
});
});
The sweetspot that you are missing is the return next(...)
That's because you're doing it wrong: you already threw an Error (which will be processed by Express and return a 500 - Error page for the user or something like that) but you are also trying to send your own response to the client: res.send('event found!');
You should really check out the Express guide about Error Handling here: http://expressjs.com/guide/error-handling.html
What I would do in your example is:
function NotFound(msg){
this.name = 'NotFound';
Error.call(this, msg);
Error.captureStackTrace(this, arguments.callee);
}
app.get('/event/:id', function(req, res, next){
if (req.params.id != 1) {
throw new NotFound('Cannot find event ' + req.params.id);
} else {
res.send('event found!');
}
});
app.error(function(err, req, res, next){
if (err instanceof NotFound) {
res.render('404.ejs');
} else {
next(err);
}
});
You have a couple of problems in your code:
When responding to the client, you need to use the response object (res rather than req).
When sending an error to next, you should return, so the rest of the function doesn't run.
Here's your code after fixing those errors:
app.get('/event/:id', function(req, res, next) {
if (req.params.id != 1) {
return next(new Error('cannot find event ' + req.params.id));
}
res.send('event found!'); // use res.send (NOT req.send)
});