I'm making a node/express app with models for users and activities. I've set up an activities.js controller and restful view-pages with placeholder text. When I try to load any of the view pages I'm getting Cannot get error messages (eg "Cannot GET /activities/edit"). The following is an example of how part of the controller is laid out:
var Activity = require('../models/Activity');
function activitiesIndex(req, res){
Activity.find({}, function(err, activities){
if(err) return console.error(err);
else{
res.render('/activities/index', {
activities: activities});
}
});
}
function activitiesIndex(req, res){
Activity.findById(req.params.id,
function(err, activity){
res.render('/activities/show', {activity: activity});
});
}
Console is showing a server 404 error, which I'm confused by as I've set up views. Does anyone have any suggestions as to where I might be going wrong here?
Thanks very much
Related
I can't seem to wrap my head around how to properly handle errors.
The basic 404, is no problem (simply set header 404 and render 'not found' page). But let's say for example:
You find a user by id, but the user doesn't exist. I suppose for this you set the header-status to 500. But how do you redirect the page back (or simply assign a redirect page) and set a flashmessage?
In most tutorials I usually find the following:
model.SignUp.forge({id: req.params.id}).fetch({withRelated: ['usermeta']}).then(function(user) {
res.render('admin/pages/users/details', {title: 'Signups', error: false, details: user});
}).catch(function(err) {
res.status(500).json({error: true, data: {message: err.message}});
});
You simply catch the problem whenever an error occurs. I also come across this sometimes:
transporter.sendMail(mailOptions, function(err) {
if(err) {
req.flash('error', 'blablabla');
res.redirect('back');
}
});
In the first case you return a json file but no redirect or render. In the second part no status has been provided.
What practices do you guys implement?
I'm a huge fan of central error handling in my express apps. How does this work? Well, I have a library of HTTP error objects that all have a 'status' property on them. All my route handlers and middeware return a callback with one of those error objects depending on what happened, and do not call res.send (or any other res.* method) if there was an error. I then have an error handling middleware (or more than one, if I it's getting to be complex) that decides if I want to do a redirect or just send the response code, or whatever depending on the needs of the app.
Taking your example:
app.post('/signup', function(req, res, next){
model.SignUp.forge({id: req.params.id}).fetch({withRelated: ['usermeta']}).then(function(user) {
res.render('admin/pages/users/details', {title: 'Signups', error: false, details: user});
}).catch(function(err) {
return next(new HttpServerError(err));
});
}
an HttpServerError has a status of 500, and so I have at least a 'catch all' error handling middleware that looks like this (in the case of a json api):
app.use(function(err, req, res, next){
console.log(err.stack);
res.status(err.status).send({message: err.clientMessage});
});
You can also do multiple handlers, and render or redirect based on the state of the request (e.g. accepts headers or type of error).
For example, in a traditional web app, I might use the name of the error to figure out what template to render, and I might redirect to a login page if it's a 403 error.
For sake of completeness, here's an example HttpServerError:
'use strict';
const util = require('util');
function HttpServerError(message){
this.message = message;
this.clientMessage = 'Dangit! Something went wrong on the server!';
this.status = 500;
Error.captureStackTrace(this, NotFoundError);
}
util.inherits(HttpServerError, Error);
HttpServerError.prototype.name = 'HttpServerError';
module.exports = HttpServerError;
I have an Express app, and ran into a problem that I should know how to solve.
I have this URL that I am trying to GET
http://localhost:3000/users/546c2b15a340bb881f853fa6/teams/newTeam
however, I get this error:
CastError: Cast to ObjectId failed for value "newTeam" at path "_id"
the easy solution would be change my app from this:
http://localhost:3000/users/546c2b15a340bb881f853fa6/teams/newTeam
into this:
http://localhost:3000/users/546c2b15a340bb881f853fa6/newTeam
however, I should probably figure out how to parse different params in URLs..any other way good way to fix it?
I believe my app is trying to take "/newTeam" and turn into into an MongoDB _id in this method and that's where things are going wrong:
app.param('team_id', function(req, res, next, team_id) {
var userTeam = TeamModel.getNewTeam(user_db);
userTeam.findById(team_id, function(err, team) {
if (err) {
return next(err);
}
if (!team) {
return new Error("no team matched");
}
req.team = team;
next();
});
});
You can create routes like this in the following order:
app.get("/users/:userId/teams/newTeam", routeHandler1);
app.get("/users/:userId/teams/:team_id", routeHandler2);
Now, app.param("team_id", handler) will only be called when team_id doesn't contain the value "newTeam".
I'm converting an MS Access database to a webapp. I'm using Angular JS, Node JS with the express framework and MySQL as database.
In ms access you don't have any edit/save features. When you edit something, the database changes instantly. I like this. Feels smooth. So I want to have this the same way in the web app. My question is. Will there be any problems with this approach in my webbapp?
This is a piece of my node js code which updates the database with a restcall:
/*
Post /api/products/ HTTP/1.1
*/
exports.editProduct = function(req, res) {
console.log(req.body);
var post = [{title_en: req.body.title_en},req.params.id];
if (connection) {
connection.query("UPDATE products SET ? WHERE id = ?", post, function(err, rows, fields) {
if (err) throw err;
res.contentType('application/json');
res.write(JSON.stringify(rows));
res.end();
});
}
};
And on the client side I use the a the $resource object
$scope.save = function(){
$scope.product.$save(function(){
console.log('Save successfull);
});
};
And in the view. I simply have inputs with ng-change:
<input ng-model="product.title_en" ng-change="save()".
Will this work good in production mode with a couple hundred users? Is the chances of blocking/crashing etc?
The only thing I see is if (err) throw err;
if there is an error the server crash so change it with a json response with a 500 status.
By the way express has a build-in way to output json
It's better off to validate title_en and id
exports.editProduct = function(req, res) {
console.log(req.body);
var post = [{title_en: req.body.title_en},req.params.id];
if (connection) {
connection.query("UPDATE products SET ? WHERE id = ?", post, function(err, rows, fields) {
if (err) {
return res.json(500,{ error: 'Cannot update the product' });
}
res.json(200,rows);
});
}
an other thing try to use restangular instead of resource it's a lot of fun :)
};
Hi i am developing nodejs application. I am inserting data to mongodb but my page always in 'loading' mode. But strange thing is my data inserted to mongodb immediately but page load not stopping. My code is shown below:
app.post('/Management/Post/New',function(req, res){
new Post({
title:req.body.post.title,
body:req.body.post.body,
keywords:req.body.post.keywords
}).save(function (err, docs){
if(err) {
return res.render(__dirname + "/views/createpost", {
title: 'Yeni Gönderi Oluştur',
stylesheet: 'postcreate',
error: 'Gönderi oluşturulurken bir hata ile karşılaşıldı'
});
}
console.log('Gönderi oluşturuldu');
});
});
Have no idea.
You only send a response when there is an error. If there's no error, you server never sends anything back: that's why the page seems to always be loading.
You need to send a response when you have no error, like this:
.save(function (err, docs){
if(err) { // Executed when there was an error with Mongo
return res.render(...);
} else { // Executed when everything is fine
return res.render(...);
}
});
You aren't handling the success scenario except for a console.log. You need a res.render() or res.redirect() on success, not just error
The following code is the user-facing part of a new node app we are building:
var loadInvoice = function(req, res, next) {
Invoice.findById(req.params.invoiceId, function (err, invoice) {
if (err) {
res.send(404, 'Page not found');
} else {
req.invoice = invoice;
next();
}
});
};
app.namespace('/invoices/:invoiceId', loadInvoice, function () {
app.get('', function(req, res){
var templateVals = {
//some template data
};
res.render('paymentselection', templateVals);
});
app.post('', function(req, res){
var data = {
// some data for the apiCall
};
someAPI.someRequest(data, function(err, data) {
console.log(res.status());
res.redirect(data.url);
});
});
});
The first method returns a confirmation page where the user presses a button to post to the same url, which triggers a redirect to an external website.
This all works exactly once. Every second request will crash the app with the message Cant set headers after they are sent. After carefull inspection of the code I could find no reason for this to happen so I added the console.log line which indeed confirms the location header has been set. But it is set to the value i got from someAPI on the previous request not the current one.
This makes absolutely no sense to me. I do not store this value anywhere nor do I do caching or persistence of this data in any way.
Does anybody know what could be causing this?
I use express, express-namespace, mogoose and swig
I found out the problem was being caused bij the 'Restler' libaray used within 'someAPI'. I have no idea how this is possible but swapping it out with something else fixed the problem.