Console.log(err) is crashing my website - node.js

I'm currently a student studying Web Development with Node. I recently was reviewing RESTful routes. I was building a blog site to do so. I was setting up a route to show a specific blog "/blogs/:id" which lets you see all the contents of a blog. Here's the route:
app.get("/blogs/:id", function(req, res){
blog.findById(req.params.id, function(err, blog){
if(err){
console.log(err)
} else{
res.render("show", {body: blog});
}
})
})
When I access the route using the browser, it loads forever and I get the following error in the terminal:
{ CastError: Cast to ObjectId failed for value "app.css" at path "_id" for model "blog"
at MongooseError.CastError (/home/ubuntu/workspace/RESTful/node_modules/mongoose/lib/error/cast.js:29:11)
at ObjectId.cast (/home/ubuntu/workspace/RESTful/node_modules/mongoose/lib/schema/objectid.js:158:13)
at ObjectId.SchemaType.applySetters (/home/ubuntu/workspace/RESTful/node_modules/mongoose/lib/schematype.js:724:12)
at ObjectId.SchemaType._castForQuery (/home/ubuntu/workspace/RESTful/node_modules/mongoose/lib/schematype.js:1113:15)
at ObjectId.SchemaType.castForQuery (/home/ubuntu/workspace/RESTful/node_modules/mongoose/lib/schematype.js:1103:15)
at ObjectId.SchemaType.castForQueryWrapper (/home/ubuntu/workspace/RESTful/node_modules/mongoose/lib/schematype.js:1082:15)
at cast (/home/ubuntu/workspace/RESTful/node_modules/mongoose/lib/cast.js:303:32)
at Query.cast (/home/ubuntu/workspace/RESTful/node_modules/mongoose/lib/query.js:3355:12)
at Query._castConditions (/home/ubuntu/workspace/RESTful/node_modules/mongoose/lib/query.js:1327:10)
at Query._findOne (/home/ubuntu/workspace/RESTful/node_modules/mongoose/lib/query.js:1552:8)
at process.nextTick (/home/ubuntu/workspace/RESTful/node_modules/kareem/index.js:333:33)
at _combinedTickCallback (internal/process/next_tick.js:73:7)
at process._tickCallback (internal/process/next_tick.js:104:9)
message: 'Cast to ObjectId failed for value "app.css" at path "_id" for model "blog"',
name: 'CastError',
stringValue: '"app.css"',
kind: 'ObjectId',
value: 'app.css',
path: '_id',
reason: undefined,
model:
{ [Function: model]
hooks: Kareem { _pres: [Object], _posts: [Object] },
base:
Mongoose {
connections: [Object],
models: [Object],
modelSchemas: [Object],
options: [Object],
_pluralize: [Function: pluralize],
plugins: [Object] },
modelName: 'blog',
model: [Function: model],
db:
NativeConnection {
base: [Object],
collections: [Object],
models: [Object],
config: [Object],
replica: false,
options: null,
otherDbs: [],
relatedDbs: {},
states: [Object],
_readyState: 1,
_closeCalled: false,
_hasOpened: true,
_listening: false,
_connectionOptions: [Object],
client: [Object],
name: 'restful_routing_revision',
'$initialConnection': [Object],
db: [Object] },
discriminators: undefined,
'$appliedMethods': true,
'$appliedHooks': true,
schema:
Schema {
obj: [Object],
paths: [Object],
aliases: {},
subpaths: {},
virtuals: [Object],
singleNestedPaths: {},
nested: {},
inherits: {},
callQueue: [],
_indexes: [],
methods: {},
methodOptions: {},
statics: {},
tree: [Object],
query: {},
childSchemas: [],
plugins: [Object],
s: [Object],
_userProvidedOptions: {},
options: [Object],
'$globalPluginsApplied': true,
_requiredpaths: [] },
collection:
NativeCollection {
collection: [Object],
opts: [Object],
name: 'blogs',
collectionName: 'blogs',
conn: [Object],
queue: [],
buffer: false,
emitter: [Object] },
Query: { [Function] base: [Object] },
'$__insertMany': [Function],
'$init': Promise { [Object], catch: [Function] } } }
But for some reason, when I change the callback to be the following:
app.get("/blogs/:id", function(req, res){
blog.findById(req.params.id, function(err, blog){
if(err){
res.redirect("/")
} else{
res.render("show", {body: blog});
}
})
})
The website works perfectly fine. I also tried removing the header from the show.ejs(the file being rendered when accessing the route) while keeping the console.log(err) and it also solved the problem. I tried removing the header because the header contains the tag that links the app.css file which I saw mentioned in the error. I would like to know what's wrong in console.log(err) with the css file.
p.s. I am using Expres for the routes and mongoose to access the MongoDB database. "blog" is the array of blogs. Incase you want to take a look at my show.ejs file, here it is:
<% include partials/header %>
<h1><%= body.title%></h1>
<img src="<%=body.image%>">
<p><%=body.body%></p>
<div><%=body.created%></div>
<% include partials/footer %>
And if you want to take a look at the app.css file, here it is:
img{
max-width: 600px;
width: 600px;
}
And if you want to take a look at the header.ejs file, here it si:
<!DOCTYPE html>
<html>
<head>
<title>Blogs Website</title>
<link rel="stylesheet" type="text/css" href="app.css">
</head>
<body>
Here is the full app.js file (the file containing the routes):
var express = require("express"),
app = express(),
mongo = require("mongoose"),
bodyParser = require("body-parser"),
expressSanitizer = require("express-sanitizer"),
methodOverride = require("method-override");
mongo.connect("mongodb://localhost/restful_routing_revision");
app.use(bodyParser.urlencoded({extended: true}));
app.use(expressSanitizer());
app.set("view engine", "ejs");
app.use(express.static("public"));
app.use(methodOverride('_method'));
var blogSchema = new mongo.Schema({
title: String,
body: String,
image: String,
created: {type: Date, default: Date.now}
});
var blog = mongo.model("blog", blogSchema);
app.get("/", function(req, res){
res.render("landing");
});
app.get("/blogs", function(req, res){
blog.find({}, function(err, body){
if(err){
console.log(err)
}else{
res.render("index", {blogs: body})
}
})
})
app.get("/dogs/new", function(req, res){
res.render("new");
})
app.post("/dogs", function(req, res){
var blogBody = req.body.blog;
blog.create(blogBody, function(err, body){
if(err){
console.log(err)
}else{
res.redirect("/blogs")
}
})
})
app.get("/blogs/:id", function(req, res){
blog.findById(req.params.id, function(err, blog){
if(err){
// res.redirect("/")
console.log(err)
} else{
res.render("show", {body: blog});
}
})
})
// blog.findById(req.params.id, function(err, blog){
// if(err){
// res.redirect("/");
// } else {
// res.render("show", {body: blog});
// }
// });
// });
app.listen(process.env.PORT, process.env.IP, function(){
console.log("The Server has Started!!!!");
})
There are alot of npm packages on top that I'm planning to use later. And I know that the blog Schema isn't well formatted. I also tried doing console.log(err) and res.redirect("/") at the same time, I arrive to the show page but still get the same error.

Just use absolute path /style.css instead of relative path style.css.
Explanation:
You are using app.use(express.static("public")); which will make the route app.get("/blogs/:id", function(req, res){...}); when triggered it tries to render style.css in your html link tag because it meets the route path as /blogs/style.css since your public folder is in the same level with blogs, so by putting / in front of style.css makes it an absolute path, so execution will start the path from the seed, and not continue down from blogs.
Another solution is to just handle triggering the route blogs/style.css by actually creating a route for it as follows:
app.get('/campgrounds/app.css', function(req, res) {
break;
});
Make sure to put it before the route app.get("/blogs/:id", function(req, res){...}); to be executed first, if triggered.
I hope this helps.

Regarding the CastError, I don't know what is going on in the underlying ejs code that causes it to try to run a Mongo query with the css filename, but this post explains how to fix your syntax (read the answer's comments about using a relative path for the css name):
NodeJS error when rendering page:Cast to ObjectId failed for value "styles.css" at path "_id"
I think that will get rid of the error in your endpoint.
For the headline question about crashing the server and the observation that:
When I access the route using the browser, it loads forever
is because the endpoint does not ever issue a response to the client when you get an error. All endpoints need to respond to the client in some way. In your case, the documented1 recommendation is to call the Express middleware function next:
blog.findById(req.params.id, function(err, blog){
if(err){
console.log(err);
next(err);
} else{
The next function will return an error result to the client browser. You need to use next because the .find function of your Mongoose model is asynchronous and Expresses next function is designed to deal with this correctly.
A separate detail, from what you posted, your Express server is most likely not crashing. It is logging the console message with an error just like you asked then continuing on waiting for new requests (logging an error to the console is perfectly ok!). If it crashed, you would likely get a 500 error page in the browser and the node process would terminate. I mention this in hopes to help future debugging. I think if you had searched on the client issue of the endpoint not returning, you would likely have found an existing answer about endpoints that never return to the client (this is a common issue to run into when getting started). I hope that helps!
Express Error Handling Doc

You have to put this line at the end
In app.js file
cut this line and paste it at the end:
app.use(express.static("public"));

Related

mongo db data not returned in resolver function for graphql but working in routes of my nodejs server

I am setting up a node js environment based on hapi, graphql and mongodb. I am able to make connection to mongodb and retrieve and display data in the GET/POST routes using db mongoose schemas. But data is not getting retrieved when the model is passed to the resolver function of graphql. Please find below my graphql resolver function
const resolvers = (shows)=>({
myQuery:{
testFunction(){
return "returned from custom test function";
},
getShowByName: function(_,args){
var out= shows.findOne();
console.log(out); //returning a huge json response instead of proper data
return out={
_id:"5349b4ddd2781d08c09890f3",
title: "test",
version: "test",
showDetails: [{
name: args.showSchemaName,
genre: "test",
lead_actor: "test"
}]
}
;
},
},
myMutation: {
createShow: function(_,args){
return args.showTypeInputDetails.title+","+args.showTypeInputDetails.version;
}
}
});
module.exports = resolvers;
Console.log(out) is letting out a huge json response which is not coming from the mongo db. The json response is really huge and also has my connection parameters, credentials and other details, hence, i am posting the beginning of the response here
Query {
_mongooseOptions: {},
_transforms: [],
mongooseCollection:
NativeCollection {
collection: Collection { s: [Object] },
opts:
{ bufferCommands: true,
capped: false,
'$wasForceClosed': undefined },
name: 'shows_details',
collectionName: 'shows_coll',
conn:
NativeConnection {
base: [Object],
collections: [Object],
models: [Object],
config: [Object],
replica: false,
Please help me in understanding why this response in coming when the findOne() is triggered from resolvers functions and proper results when the same function is triggered from the routes function.
[shows is my mongoose db model]
why don't you try like below code.
dbo.collection("collection_name").findOne({}, function(err, result) {
if (err) throw err;
console.log(result.name);
db.close();
});
i made my resolver function async, and returned the data with await and that solved the problem

Mongoose find returning odd object

my current problem is with the db.collection.find() mongoose command. I'm relatively new to mongoose/mongodb, but I've gotten the hang of the concepts of it. Here is the test code I've been trying to run:
mongoose.connect(url);
function main()
{
var db = mongoose.connection;
db.on('open', function() {
db.collection('Tweet').find({id: 631460910368956400}, function (err, data){
console.log(data);
})
/*var coll = db.collection('Tweet');
db.collection('Tweet').findOne({id: 631460910368956400},function (err, ret) {
if(err) console.log(err);
console.log(ret['id']);
//db.close();
});*/
});
}
main();
The data returned from the non commented out field is a strange object:
{ connection: null,
server: null,
disconnectHandler:
{ s: { storedOps: [], storeOptions: [Object], topology: [Object] },
length: [Getter] },
bson: {},
ns: 'TEST.Tweet',
cmd: { find: 'TEST.Tweet', limit: 0, skip: 0, query: {}, slaveOk: false },
options:
{ skip: 0,
limit: 0,
raw: undefined,
hint: null,
timeout: undefined,
slaveOk: false,
db:
{ domain: null,
_events: [Object],
_maxListeners: undefined,
s: [Object],
serverConfig: [Getter],
bufferMaxEntries: [Getter],
databaseName: [Getter],
etc etc... it goes on for much longer.
The IP address is a remote connection that successfully connects. I can do things like add and remove documents, but cannot actually view the documents from the javascript. I know that it is caused due to some kind of asynchronous problem, however I'm not sure how to fix it. Also, the commented out code for .findOne() seems to pull data completely fine in the code above.
What would be the problem with the code for the .find() function? An explanation for why the current error in data retrieving would be great also.
Thanks for your help!
The object you receive is a Cursor which is an object used to retrieve the actual results.
When you are sure your query will never return more than one object (like in this case where you query by the always unique _id field), you can use db.collection('Tweet').findOne( which will return just that object without the additional layer of indirection.
But when your query can potentially return more than one document, you need to use a cursor. To resolve the cursor, you can turn it into an array of documents by using cursor.toArray:
db.collection('Tweet').find({}, function (err, cursor){
cursor.toArray().forEach(function(doc) {
console.log(doc);
});
})
This is the most simple version. For more information about cursors, refer to the documentation linked above.
By the way: So far you only used the functionality of the native driver. When you want to use Mongoose to query objects, you might want to use the methods of the Mongoose model object.

Get the correct result while executing a find query on mongodb using node

So I am trying to run a nodejs script to make some custom action on a mongo database. The problem I am facing is with the following script -
// a valid id obtained before
collection.find({"id":id}, function(err, result) {
if(err) {
console.log("Could not select");
} else {
console.log("Select successful for id: " + id);
console.log(result);
}
});
Now when I check the result after running this, I only see data about the db, a whole lot of it that is not really concerned with the select query. What I want is what anyone would expect! A list of the documents for that id. Obviously, I am missing something here, could anyone please point me to it?
EDIT:
So when I run the query on the mongo shell, I get the expected result.
db.messages.findOne({"id":"<a random id that has a json inserted in mongo>"})
However, when I run it from the script shown above, all I get is this:
Select successful for id: <random uid from above>
{ db:
{ domain: null,
_events: {},
_maxListeners: 10,
databaseName: 'test',
serverConfig:
{ domain: null,
_events: [Object],
_maxListeners: 10,
_callBackStore: [Object],
_commandsStore: [Object],
auth: [Object],
_dbStore: [Object],
options: [Object],
_serverState: 'connected',
_haProcess: [Object],
servers: [Object],
strategyInstance: [Object],
emitOpen: false,
.....
.....
.....
Thanks
The result parameter that find provides to the callback is a cursor, not an array of results. Call toArray to iterate over the resulting cursor and get an array of docs:
collection.find({"id":id}).toArray(function(err, result) {
if(err) {
console.log("Could not select");
} else {
console.log("Select successful for id: " + id);
console.log(result);
}
});
Or if id uniquely identifies a single doc, use findOne instead:
collection.findOne({"id":id}, function(err, result) {
if(err) {
console.log("Could not select");
} else {
console.log("Select successful for id: " + id);
console.log(result);
}
});

Connected clients in express.io

I'm developing a simple chat app using node.js and express.io
I would like to display a list of the connected clients (or online for chat) all the time.
In express.io's doc, there is no clear way on how to "get" the list of connected clients once a new one has entered the room, i.e there is just the "broadcast" but not the "get".
Have someone done this before?
Any clues will be really helpful.
Thanks!
Edit:
After trying #jibsales's answer. I think we are almost there. What clients returns me is not the actual array of clients but this one:
[ { id: 'OWix3sqoFZAa20NLk304',
namespace:
{ manager: [Object],
name: '',
sockets: [Object],
auth: false,
flags: [Object],
_events: [Object] },
manager:
{ server: [Object],
namespaces: [Object],
sockets: [Object],
_events: [Object],
settings: [Object],
handshaken: [Object],
connected: [Object],
open: [Object],
closed: [Object],
rooms: [Object],
roomClients: [Object],
oldListeners: [Object],
sequenceNumber: 496205112,
router: [Object],
middleware: [],
route: [Function],
use: [Function],
broadcast: [Function],
room: [Function],
gc: [Object] },
disconnected: false,
ackPackets: 0,
acks: {},
flags: { endpoint: '', room: '' },
readable: true,
store: { store: [Object], id: 'OWix3sqoFZAa20NLk304', data: {} },
_events:
{ error: [Function],
ready: [Function],
connection: [Function],
NewChatPrivateLine: [Function],
NewIdea: [Function],
NewChatLine: [Function],
NewPost: [Function] } } ]
The functions are:
var app = require('express.io')();
app.io.route('connection', function(req) {
req.io.join(req.data.room);
var clients = app.io.sockets.clients(req.data.room);
console.log(clients)
app.io.room(req.data.room).broadcast('announce', {
user: req.data.user,
clients: clients
})
});
This actually returns an error ( data = JSON.stringify(ev); TypeError: Converting circular structure to JSON) as the array has several circular objects and hence it cannot be broadcasted.
Any thoughts?
Because express.io is simply glueing express and socket.io, don't forget to look at socket.io's documentation as well. With that said, since socket.io v0.7, we now have an API method to get this information:
var clients = io.sockets.clients('room'); // all users from room `room`
Unfortunately express.io is written in coffeescript (UGGGH!!!) so I'm having a hard time reading the source, but it looks like when you require the express.io module, the socket.io instance is hoisted up as well:
var express = require('express.io');
var clients = express.io.sockets.clients('room'); // all users from room `room`
If this doesn't work, I would ditch express.io for a manual configuration with express and socket.io because it looks like express.io has a VERY opinionated API. Its really not that hard at all as express.io is doing nothing more than creating a pretty interface/abstraction to manual configuration (which is actually hurting you in this use case if the above doesn't work).
I would also checkout SockJS as I (and many other websocket consumers) ditched socket.io for SockJS due to a lack of community support. Not to mention, there is a SEVERE memory leak in IE9 when falling back to xhr-polling.
Well, finally I went with the "tacking" solution proposed by #Brad. It is not the most elegant but, if you can help me improve it, It'd be awesome!!
This is the final code:
Server-side
var app = require('express.io')();
//To broadcast the users online in room sent by the client
var clients = [];
app.io.route('connect', function (req) {
req.io.leave(req.data.room).on('disconnect', function() {
//To remove client from list when disconnected
var index = clients.indexOf(req.data.user);
if (index > -1) {
clients.splice(index, 1);
}
app.io.room(req.data.room).broadcast('announce', {
user: req.data.user,
clients: clients
})
});
req.io.join(req.data.room);
//To avoid repeating the same client with several opened windows/tabs
var index = clients.indexOf(req.data.user);
if (index === -1) {
clients.push(req.data.user);
}
app.io.room(req.data.room).broadcast('announce', {
user: req.data.user,
clients: clients
})
});
Client-side
// Emit ready event with person name and predefined room for who's online
io.emit('connect', {
room: room,
user: user
});
//Get the signal from server and create your list
io.on('announce', function (data){
//Do awesome stuff with data
});

ExpressJS res.render() error (JSON.stringify can't work on circular reference)

What's wrong here?
res.render('/somepage', {user:req.session.user})
It leads to Converting circular structure to JSON errors, (results in session element that has a circular user reference.)
exports.home = function (req, res) {
var entityFactory = new require('../lib/entity-factory.js').EntityFactory();
entityFactory.get_job_task_lists({
callback : function (err, job_task_lists) {
res.render('home.jade', {
locals:{
title: 'Logged in.',
user:req.session.user, // does not work
job_task_lists:job_task_lists || []
}
});
}
});
};
I added some logging in node_modules/express/node_modules/connect/lib/middleware/session/memory.js
MemoryStore.prototype.set = function(sid, sess, fn){
var self = this;
process.nextTick(function(){
console.log(sess); //this is giving the output listed
self.sessions[sid] = JSON.stringify(sess);
...
This is what I expect the session to look like, in terms of structure:
{ lastAccess: 1330979534026,
cookie:
{ path: '/',
httpOnly: true,
_expires: Tue, 06 Mar 2012 00:32:14 GMT,
originalMaxAge: 14399999 },
user: // this is the object I added to the session
{ id: 1,
username: 'admin',
password: '8e3f8d3a98481a9073d2ab69f93ce73b',
creation_date: Mon, 05 Mar 2012 18:08:55 GMT } }
But here's what I find:
{ lastAccess: 1330979534079, // new session
cookie:
{ path: '/',
httpOnly: true,
_expires: Tue, 06 Mar 2012 00:32:14 GMT,
originalMaxAge: 14399999 },
user: // but here it is again, except now it's a mashup,
// containing members it shouldn't have, like locals,
// and, well, everything but the first 4 properties
{ id: 1,
username: 'admin',
password: '8e3f8d3a98481a9073d2ab69f93ce73b',
creation_date: '2012-03-05T18:08:55.701Z',
locals:
{ title: 'Logged in.',
user: [Circular], //and now it's circular
job_task_lists: [Object] },
title: 'Logged in.',
user: [Circular],
job_task_lists: [ [Object], [Object], [Object], getById: [Function] ],
attempts: [ '/home/dan/development/aqp/views/home.jade' ],
scope: {},
parentView: undefined,
root: '/home/dan/development/aqp/views',
defaultEngine: 'jade',
settings:
{ env: 'development',
hints: true,
views: '/home/dan/development/aqp/views',
'view engine': 'jade' },
app:
{ stack: [Object],
connections: 6,
allowHalfOpen: true,
_handle: [Object],
_events: [Object],
httpAllowHalfOpen: false,
cache: [Object],
settings: [Object],
redirects: {},
isCallbacks: {},
_locals: [Object],
dynamicViewHelpers: {},
errorHandlers: [],
route: '/',
routes: [Object],
router: [Getter],
__usedRouter: true },
partial: [Function],
hint: true,
filename: '/home/dan/development/aqp/views/home.jade',
layout: false,
isPartial: true } }
node.js:201
throw e; // process.nextTick error, or 'error' event on first tick
^
TypeError: Converting circular structure to JSON
at Object.stringify (native)
at Array.0 (/home/dan/development/aqp/node_modules/express/node_modules/connect/lib/middleware/session/memory.js:77:31)
at EventEmitter._tickCallback (node.js:192:40)
See how the user object is nested?
Note that this time I did not send values in explicitly with 'locals' but it ended up in one (thats the source of the circular reference.
It looks like the session is being used to transfer objects to the view.
Here's my only middleware (it only reads from the session):
function requiresAuthentication(req, res, next){
if (req.session.user){
next();
} else {
next(new Error('Unauthorized. Please log in with a valid account.'))
}
}
and the only time I modify the req.session is in this route:
app.post('/home', function (req,res,next) {
var auth = require('./lib/authentication');
auth.authenticate_user(req.body.user, function (user) {
if (user){
req.session.user = user;
console.log('authenticated');
res.redirect(req.body.redir || '/home');
//next();
} else {
console.log('not authenticated');
res.render('logins/new.jade', {title: 'Login Failed', redir:''})
}
});
});
I don't have much else going on in my application yet, as it's still quite young. I know I'm not mangling the session anywhere myself; I checked.
I did some more testing, and it appears this is only an issue when I then try to use the local variable on a page. For instance, here is my view home.jade
div(data-role="page")
div(data-role="header")
a(href='/logout', data-icon='delete', data-ajax="false") Log out
h1= title
a(href='/account', data-icon='info', data-ajax="false") Account
!= partial('user', user)
each jtl in job_task_lists
div(id=jtl.name, class = 'draggable_item', style='border:2px solid black;')
#{jtl.name} - #{jtl.description}
a(data-icon='plus')
div(data-role="footer")
h3 footer
script(src="/javascripts/home.js")
If I comment out the user partial, it renders, else I get this Converting circular structure to JSON issue.
UPDATE
So after hooking up eclipse and the v8 debugger, I have been stepping through the code and I know where the mashup of session and user objects is occurring,
in node_modules/connect/lib/middleware/session/session.js
utils.union ends up mashing the members of the user object into the session, causing the circular reference. I'm just not sure why (admittedly probably my code)
This was a problem with session data being modified in a view.
After much digging, I found that it was a bug in the way partials are handled in 2.5.8. I submitted an issue, and subsequently a patch. (in case anyone needs this info at a future date) as npm is still serving up Express 2.5.8 AFAIK.
Thanks for your help #freakish and #Ryan

Resources