Express.js Routes Hang on everything but the homepage - angularjs

I'm building an app and learning the MEAN stack. I successfully followed a tutorial on thinkster last night and was able to get everything working as expected. Now, however, while trying to do this myself, I'm running into issues. The homepage of my app "burbank" loads fine, but the 3 routes I've created just hang. No errors, nothing in terminal, just try forever to load.
localhost:3000 loads fine
localhost:3000/contacts hangs
index.js
var mongoose = require('mongoose');
var Contact = mongoose.model('Contact');
var Event = mongoose.model('Event');
var Vehicle = mongoose.model('Vehicle');
var express = require('express');
var router = express.Router();
router.get('/contacts', function(req, res, next) {
Contact.find(function(err, contacts){
if(err){ return next(err); }
res.json(contacts);
});
});
router.get('/events', function(req, res, next) {
Event.find(function(err, events){
if(err){ return next(err); }
res.json(events);
});
});
router.get('/vehicles', function(req, res, next) {
Vehicle.find(function(err, vehicles){
if(err){ return next(err); }
res.json(vehicles);
});
});
App.js
var mongoose = require('mongoose');
mongoose.connect = ('mongodb://localhost/burbank');
require('./models/Contacts');
require('./models/Events');
require('./models/Vehicles');
var routes = require('./routes/index');
var users = require('./routes/users');
I originally thought this had to do something with the order that I was placing my requires and variables in app.js, but I don't think that's the case. At any rate, help is much appreciated. I'm slowly grasping all these concepts.

Sometimes all it takes is a weekend away, a hike at the Grand Canyon and 16 hours in the car to find a syntax error.
connect.mongoose = ('mongodb://localhost/burbank');
DOES NOT EQUAL
connect.mongoose('mongodb://localhost/burbank');
To those of you who assisted me, thank you very much. Pardon me while I hang my head in shame.

According to Mongoose docs, the first parameter for find is a dictionary with the filter you want to apply to documents:
http://mongoosejs.com/docs/api.html#model_Model.find
Try something like this:
Contact.find().exec(function(err, contacts) { ...

Try checking to see if the routing works without the mongoose layer using: res.send("example");
When using the .find function in mongoose I believe that you have to pass an empty object as the first parameter (if you want to return the entire collection).
Try changing this:
Contact.find(function(err, contacts){
To this:
Contact.find({}, function(err, contacts){
Repeat that for all of your find queries.

Related

How to access Node JS route Url in Angular JS site

I am working on a site which is in Angular JS language. Now for website, I have to generate dynamic sitemaps and for this I used Node JS and created a xml.js route in node and wrote hello world.
Now the problem is, I am not able to use access this xml.js in angular site. Here is xml.js code :
var express = require("express");
var router = express.Router();
router.get("/test", function() {
console.log("hello world");
});
module.exports = router;
Here is server.js code :
var express=require('express');
var xml = require("./xml");
var app=express();
app.use('/xml',xml);
app.use('/',express.static('app'));
app.listen(9000) ;
Now whenever I try to access http://192.168.0.19:9000/xml/test I am being redirected to home page always.
Can someone help me out ?
You can try this code.This code work for me
You need to pass req and res parameter.
router.get('/', function (req, res) {
res.send('home page')
})
router.get("/test", function (req, res) {
console.log("hello world");
res.send('test page')
})

Admin on Rest Mongoose compatible queries

I am using Admin on Rest to create a dashboard for my rest calls.
The call is going through and I looked at the call in my console.
GET /api/v2/admin/user?_end=10&_order=DESC&_sort=id&_start=0 200 61.102 ms - 2846
But it isn't returning anything, which I assume is because Mongo doesn't take in queries with _end, _order, _start, as well as it uses _id instead of id.
What would be the best workaround for this? As I can't modify the call going in.
The logic for the endpoint is below. I am also (not pictured) trying to manually create the sorting options but I feel like that isn't efficient.
// routes/admin/user.js
var express = require('express'),
router = express.Router();
var User = require(__models + 'user');
router.route('/')
.get(function(req, res, next){
var query = req.query || {};
User.find(query).then(users => {
return res.json(users);
}).catch(err => next(err));
});
module.exports = router;
You need to write your own REST Client for creating queries in formats your REST API understands.
https://marmelab.com/admin-on-rest/RestClients.html#writing-your-own-rest-client
I created a util function to do this for me.
module.exports.getJsonFromUrl = function(query) {
var result = {};
query.split("&").forEach(function(part) {
var item = part.split("=");
result[item[0]] = decodeURIComponent(item[1]);
});
return result;
};
And I called it from controller like so
var query = routeUtil.getJsonFromUrl(req._parsedUrl.query);

Post SQL data to Angular View with NodeJS

I'm having a difficult time posting data retrieved from a server using mysql with node. I have connected to my db successfully, and I can return the data I want by console logging it to the CLI when running "node server.js". However, I'm not sure how to post this data to my Angular view. No problem console logging, but this doesn't help me get data to the application.
For the moment, I'm just trying to get the data to index.html, which is my primary view and holds my ng-view portion for Angular routing. I'm probably missing something obvious bc I'm new to NodeJS.
// MODULES
var express = require('express');
var app = express();
var port = process.env.PORT || 3000;
var mysql = require('mysql');
var serveStatic = require('serve-static');
var bodyParser = require('body-parser');
var source = __dirname + '/public/views/index.html';
app.use(serveStatic(__dirname, {'index': ['index.html']}));
app.route('/*')
.get(function(req, res) {
res.sendFile(source);
});
var data;
var connection = mysql.createConnection({
host : 'thehostdb',
user : 'username', // credentials correct, connection works
password : 'pw',
database : 'db',
port: '3306'
});
connection.query('SELECT * from poemTable', function(err, rows, fields) {
if (!err) {
data = JSON.stringify(rows);
setDataValue(data);
}
else {
console.log('Error while performing Query:', err);
}
});
function setDataValue(value) {
data = value;
console.log(data); //Where the data logs
}
app.listen(port, function () {
console.log('Example app listening on port' + port + '!')
})
You have to understand what this code does, and how nodejs and angular are supposed to work together. Angular is served to the client and then rendered by the clients browser. So if you want to inject data you have to fetch it. So in your angular app when the controller starts make an api call, and in your server create a new route:
app.get('/data', function(req, res, next) {
connection.query(..., function(err, rows, fields) {
res.json(rows);
});
});
Make sure you understand node and it's async nature, what is event loop and how it works and what is callback hell, also I would check out promises and other tutorials on nodeschool.io, it's a great place to start with node :)

Why do I get a mongoose ValidationError?

I am at a beginner level with the MEAN stack, trying to work on the following tutorial: adrianmejia.com/blog/2014/10/01/creating-a-restful-api-tutorial-with-nodejs-and-mongodb/. I am using Cloud 9 online IDE.
Part of the tutorial involves testing database POST using curl and Postman. I successfully post a GET request, which at this point in the tutorial gives med an empty array.
I use
curl -XGET myc9urlhere:8080/todos - with success (getting [])
And try curl -XPOST myc9urlhere:8080/todos -d 'name=Somename&completed=false&note=somenote' - failing
The stacktrace is as follows:
ValidationError: Todo validation failed
at MongooseError.ValidationError (/home/ubuntu/workspace/todo-api/node_modules/mongoose/lib/error/validation.js:23:11)
at model.Document.invalidate (/home/ubuntu/workspace/todo-api/node_modules/mongoose/lib/document.js:1486:32)
at model.Document.set (/home/ubuntu/workspace/todo-api/node_modules/mongoose/lib/document.js:753:10)
at model._handleIndex (/home/ubuntu/workspace/todo-api/node_modules/mongoose/lib/document.js:596:14)
at model.Document.set (/home/ubuntu/workspace/todo-api/node_modules/mongoose/lib/document.js:556:24)
at model.Document (/home/ubuntu/workspace/todo-api/node_modules/mongoose/lib/document.js:68:10)
at model.Model (/home/ubuntu/workspace/todo-api/node_modules/mongoose/lib/model.js:47:12)
at new model (/home/ubuntu/workspace/todo-api/node_modules/mongoose/lib/model.js:3250:13)
at /home/ubuntu/workspace/todo-api/node_modules/mongoose/lib/model.js:1864:51
at /home/ubuntu/workspace/todo-api/node_modules/mongoose/node_modules/async/internal/parallel.js:27:9
at eachOfArrayLike (/home/ubuntu/workspace/todo-api/node_modules/mongoose/node_modules/async/eachOf.js:57:9)
at exports.default (/home/ubuntu/workspace/todo-api/node_modules/mongoose/node_modules/async/eachOf.js:9:5)
at _parallel (/home/ubuntu/workspace/todo-api/node_modules/mongoose/node_modules/async/internal/parallel.js:26:5)
at parallelLimit (/home/ubuntu/workspace/todo-api/node_modules/mongoose/node_modules/async/parallel.js:85:26)
at /home/ubuntu/workspace/todo-api/node_modules/mongoose/lib/model.js:1882:5
at Function.create (/home/ubuntu/workspace/todo-api/node_modules/mongoose/lib/model.js:1852:17)
A small note is that I have also tried this using the Chrome extension Postman. The tutorial says I must use x-www-form-urlencoded which gives the same error returned. See screenshot. And if I turn to the form-data setting instead, I actually succeed in inserting some data into the database, but just bogus stuff. See the second screenshot.
Postman fail
Postman form-data
I have really tried to research myself - maybe this tutorial is not the greatest place to start either :). Below I will include some details on the code.
Thanks a lot for any help solving this.
Identical to the tutorial, I have created a Model for a todo-list item, as shown (Todo.js):
var mongoose = require('mongoose');
var TodoSchema = new mongoose.Schema({
name: String,
completed: Boolean,
note: String
});
module.exports = mongoose.model('Todo', TodoSchema);
Now in my express routing file todos.js I have the following code:
var express = require('express');
var router = express();
//express.Router() was the original here, that failed on router.get
//as router was then undefined for some reason.
var Todo = require('../models/Todo.js');
/* GET /todos listing. */
router.get('/', function(req, res, next) {
Todo.find(function (err, todos) {
if (err) return next(err);
res.json(todos);
});
});
/* POST /todos */
router.post('/', function(req, res, next) {
Todo.create(req.body, function (err, post) {
if (err) return next(err);
res.json(post);
});
});
module.exports = router;
Because I do not know exactly what is wrong here I will also post an extract of my app.js showing my database connection
var routes = require('./routes/index');
var users = require('./routes/users');
var todos = require('./routes/todos');
var app = express();
// load mongoose package
var mongoose = require('mongoose');
// Use native Node promises
mongoose.Promise = global.Promise;
// connect to MongoDB
mongoose.connect('mongodb://'+process.env.IP+'/todo-api')
.then(() => console.log('connection succesful'))
.catch((err) => console.error(err));
app.use('/', routes);
app.use('/users', users);
app.use('/todos', todos);
And the package-json that was generated (I am using Cloud 9 IDE)
{
"name": "application-name",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node app.js"
},
"dependencies": {
"ejs": "*",
"express": "3.2.6",
"mongoose": "^4.7.6"
}
}
I think the main problem you're encountering here is that all post parameters are strings. This ends up being fine for the name and note fields of you TodoSchema, but will break when it comes to the completed field, since it is boolean. To address this, try converting the string to a boolean before creating the ToDo entry.
/* POST /todos */
router.post('/', function(req, res, next) {
req.body.completed = (req.body.completed === 'true');
Todo.create(req.body, function (err, post) {
if (err) return next(err);
res.json(post);
});
});
Also, the reason that the bogus post worked is because you aren't validating your post data. Consider making sure that the post data coming in though your route has all of the required fields, and doesn't contain anything dangerous.
Go to the data folder in your directory. Inside it there is a file mongod.lock. Delete it (you wont require root privileges) just use rm mongod.lock. Come back to main directory and enter ./mongod. hope this will solve the problem

How to pass multiple parameters in a URL Angular/REST API

I'm trying to pass multiple parameters in a URL with no luck. I'm not sure if it makes a difference but I am doing it through Angular. I'm trying to send the request to a REST API backend that I know works for single requests. Here is what my backend looks like
index.js
var express = require('express');
var router = express.Router();
var game = require('./game');
router.get('/api/v1/gameRefined/:from_datepicker:to_datepicker:from_timepicker:to_timepicker:selectLevel', game.getAllRefined);
module.exports = router;
game.js
...dbconnection stuff...
var game={
getAllRefined: function(req, res) {
var refines = req.params;
console.log("getting refined games");
pool.getConnection(function(err, connection){
var query = connection.query('SELECT * FROM game WHERE date >= ? AND date <= ? AND time >= ? AND time <= ? and level = ?', [refines.from_datepicker, refines.to_datepicker, refines.from_timepicker, refines.to_timepicker, refines.selectLevel], function(err, rows) {
connection.release();
if(err) {
throw err;
}else{
res.json(rows);
}
});
})
},
}
module.exports = game;
I send the request from this factory
.factory('gameFactory', ['$http',
function($http) {
var _gameFactory = {};
_gameFactory.getRefinedGames = function(dateFrom,dateTo,timeFrom,timeTo,level) {
var encodedParam = encodeURIComponent(baseUrl + '/api/v1/gameRefined/?from_datepicker='+dateFrom+'&to_datepicker='+dateTo+'&from_timepicker='+timeFrom+'&to_timepicker='+timeTo+'&selectLevel='+level+'');
return $http.get(encodedParam);
}
return _gameFactory;
}])
That sends this request that comes back as a 404:
http://localhost:8100/http%3A%2F%2Flocalhost%3A3000%2Fapi%2Fv1%2FgameRefined%2F%3Ffrom_datepicker%3D2015-02-05%26to_datepicker%3D2015-02-19%26from_timepicker%3D12%3A00%26to_timepicker%3D18%3A00%26selectLevel%3D1
I have tried it encoded and not encoded, with forward slashs, with semi colons, but nothing has worked so far.
I don't know why a localhost gets appended at the start, but even trying it in postman without the first localhost still is a 404 error.
How should I be doing this? Any help is appreciated. Thank you.
First, other than separating the work into a factory, you aren't really using Angular here. Second, I would consider posting to your API, return JSON results from the API, and then use a promise to read the data back into Angular.
Use $http.post
Let Angular do this work for you. Something like the below will generate the URL request for you. The return value of $http is also a promise, so using .success and .error will allow you to parse any returned data as well, even if it is just a success or failure message - but it is a great method of passing data between server/API and client.
.factory('gameFactory', ['$http',
function($http) {
return {
reachAPI: function(dateFrom, dateTo) {
$http.post('http://localhost:8080/api/v1', {
'dateFrom': dateFrom,
'dateTo': dateTo
})
.success(function(data, status, headers, config) {
*things happen*
data.somethingReturned // from your API
});
}
}]);
Consider body-parser
I know you said you have confidence in your REST API structure, but body-parser is an Express middleware that can parse URL-encoded strings and may prove helpful in reading your data. Personally, I think it lends towards more readable code.
var app = express();
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
router.route('/api').post(function(req, res) {
*things happen*
req.body.dateFrom //find your data
*things happen*
res.json(returnedData);
});
Hope that helps

Resources