Express js routing and mysql query not working - javascript

I'm just now started to learn Node and Express, I have some probelm with the routes in express. I want a well modular code for routing. I want to query some data from mysql database:
Here is my app.js(it is on "public_html" directory):
var path = require('path');
var express = require('express');
var routes = require('./routes');
var app = express();
var staticPath = path.resolve(__dirname, './');
app.use(express.static(staticPath));
routes.init(app);
module.exports = app;
app.listen(3000, function() {
console.log('Server is listening on port: 3000');
});
Next file: "public_html/routes/index.js":
exports.init = function(app){
//electronics routes
app.use('/laptop', require('./laptop'));
};
"public_html/routes/laptop/index.js":
var router = require('express').Router();
router.get('/laptop', require('./modules/laptop'));
module.exports = router;
"public_html/routes/laptop/modules/laptop.js":
var mysql = require('mysql');
var connection = mysql.createConnection(
{
host : 'localhost',
user : 'admin',
password : 'xxxxxxx',
database : 'database',
}
);
module.exports = function(req, res){
connection.connect();
var queryString = 'SELECT * FROM laptop';
connection.query(queryString, function(err, rows, fields) {
if (err) throw err;
res.writeHead(200, { 'Content-Type': 'application/json'});
res.end(JSON.stringify(rows));
});
connection.end();
};
I want to keep this modularity even if its look like a bit over complicated, in the future I will need it.
So the problem is it's just doesn't working, I think its just a stupid error somewhere, but I don't find it and on the internet there is only simple route examples so I cant use them in this case.

The problem is most likely in your routing.
You're mounting a separate router at /laptop. Within that mounted router you're setting up a /laptop (GET) route on top of that, so the full path would be /laptop/laptop.

Related

How to pass DB object in multi router setting in ExpressJS?

I would like to make multiple router settings like the example in ExpressJS Doc.
I have index.js , api1 , api2 like below.
How can I pass the db object from index.js to api1 and api2?
I try with
app.use('/api/v1', require('./controllers/api_v1')(db));
but it shows errors:Router.use() requires a middleware function but got a Object
index.js:
var express = require('../..');
const knex = require('knex');
const config = require('./config');
var app = module.exports = express();
const db = knex(config.db);
app.use('/api/v1', require('./controllers/api_v1'));
app.use('/api/v2', require('./controllers/api_v2'));
app.get('/', function(req, res) {
res.send('Hello from root route.')
});
/* istanbul ignore next */
if (!module.parent) {
app.listen(3000);
console.log('Express started on port 3000');
}
api_v1.js
var express = require('../../..');
var apiv1 = express.Router();
apiv1.get('/', function(req, res) {
res.send('Hello from APIv1 root route.');
});
apiv1.get('/users', function(req, res) {
res.send('List of APIv1 users.');
});
module.exports = apiv1;
api_v2.js
var express = require('../../..');
var apiv2 = express.Router();
apiv2.get('/', function(req, res) {
res.send('Hello from APIv2 root route.');
});
apiv2.get('/users', function(req, res) {
res.send('List of APIv2 users.');
});
module.exports = apiv2;
You could export the db object from a database.js file and require it in the index.js file as well as every other file where you need database access. Or, an easier but uglier method, would be to make the variable global via global.db = db. You could then use db everywhere in your Node.JS application.

Serve html file in nodejs server

I've been doing fine until I try to separate my code into routes, controllers and etc. Now I'm getting an error when I try to load the html file. When I go to the link http://localhost:3000/ I'm getting this error Error: ENOENT: no such file or directory, stat '/views/index.html'
This is my routes.js code
module.exports = function (app) {
var userController = require('../controllers/userController');
// app.use(require('express').static('../app/views/index.html'));
app.get('/', userController.renderHomePage);
app.post('/find', userController.getUser);
app.get('/get', userController.getUsers);
app.post('/add', userController.addUser);
}
And here's my userController.js file
var mongoose = require('mongoose');
var User = require('../models/user');
var express = require('express');
var app = express();
app.use(express.static('../app'));
exports.renderHomePage = function (req, res) {
res.sendFile('/views/index.html');
}
exports.addUser = function(req,res){
console.log(req.body);
var newUser = new User({
name : req.body.name,
username : req.body.username,
password : req.body.password
});
newUser.save(function(err){
if(err){
console.log(err);
}
else{
console.log("User Saved successfully");
}
});
res.send(req.body);
};
exports.getUsers = function (req, res) {
// body...
User.find({}, function(error, users){
if(error){
console.log(error);
}
else{
res.send(users);
}
})
};
exports.getUser = function (req, res) {
// body...
console.log(req.body);
var data = req.body.username;
User.find({username : data}, function(err, user){
if(err){
throw err
}
else{
console.log(user);
res.send(user);
}
} );
};
Here's my server.js
var express = require('express');
// var mongoose = require('mongoose');
var bodyParser = require('body-parser');
var PORT = process.env.PORT || 3000;
var app = express();
var routes = require('./api/routes/routes');
routes(app);
var database = require('./config/database');
app.use(bodyParser.json());
app.listen(PORT, function(){
console.log("Server is running on port "+PORT);
})
And here's my folder structure.
Server starting without an error. And I thought I've given the paths correctly. But I'm getting the error. Can anyone help me with this ? Thanks.
EDIT :
This is how I've linked my script to the html file
<script src="/script/app.js"></script>
It's been two months, did you solve the problem ?
If not did you try that code :
app.use(express.static('app'));
The path you give to the static function is relative to the directory where you run your node process.
In your case, you start your server with/from the server.js file (at the root directory), so the path you give to the static function is relative to this location.
A path starting with / is an absolute path, meaning it resolves based on the root directory (on Windows, something like C:\, on linux it's just /).
You should be using the path module to get paths to files relative to the module's directory like so:
var path = require('path');
var filePath = path.join(__dirname, 'relative/path/to/file');
__dirname is a special module-scoped variable that provides the path to the current module's containing directory.
app.use(express.static('../../app'))
Try adding another '..' in your userController.js file, just one .. will put you at the api directory.
Include the 'path' module and change
res.sendFile('/views/index.html');
to
res.sendFile(path.resolve(`${__dirname}/views/index.html`))
I ran into this problem. You are sending the html file with res.send, but your scripts are not in a directory that can be reached by your statically available files.
Just saw your EDIT. With your EDIT you are closing in on it. Change the reference in your HTML file of your script include.

Export functions or variables to another module in node.js

I know there are lots of questions similar to mine but I could not find the best solution.
I am creating a web app with node and rethinkdb. I want to organise different js files (modules) so that each has specific task.
I have this query.js file whose query result must be passed to routes.js file.
I have tried implement this in the following way.
query.js
//dependencies
var express = require('express');
var path = require('path');
var r = require('rethinkdbdash')({
port: 28015,
host: 'localhost',
db: 'stocks'
});
var len;
//function to get companies list
exports.clist = function(){
r.table('company')
.run()
.then(function(response){
return response;
})
.error(function(err){
console.log(err);
})
}
console.log(exports.clist[0].id)
//function to get number of entries in database
exports.clen = function(){
r.table('company')
.run()
.then(function(response){
len = Object.keys(clist).length;
return len;
})
.error(function(err){
console.log(err);
})
}
routes.js
//dependencies
var express = require('express');
var request = require('request');
var path = require('path');
var r = require('rethinkdbdash')({
port: 28015,
host: 'localhost',
db: 'stocks'
});
//query module
var query = require('./query')
clist = query.clist();
clen = query.clen();
//create router object
var router = express.Router();
//export router
module.exports = router;
//home page
router.get('/', function(req, res) {
console.log('served homepage');
res.render('pages/home');
});
//--companies page--//
router.get('/company', function(req,res){
console.log('served companies page')
res.render('pages/company', {
clist: clist,
x:clen
});
});
the console log in query.js is showing that cannot read property id of undefined.
Also I would like to know is there a way to directly pass the variables instead of using functions and then calling it.
I apologise if the solution is obvious.
To summarise I want the query result which is an object to be accessible from routes.js file.
Note: As exports.clist1 is an asynchronous method, you can't expect the result to be printed in the next line, hence comment this line and follow as below
//console.log(exports.clist[0].id)
You have to register a middleware to make this working, otherwise, query will be called only at the time of express server started and not at every request.
So you can do like this,
Hope you had something like this in your startup file (app.js),
var app = module.exports = express();
routes.js
//query module
var query = require('./query')
var app = require('../app'); // this should resolve to your app.js file said above
//clist = query.clist();
//clen = query.clen();
// middleware to populate clist & clen
app.use(function(req, res, next){
query.companyList(function(err, data){
if(!err) {
req.clist = data.clist;
req.clen= data.clen;
}
next();
});
});
query.companyList(function(err, data){
if(err) {
console.log(err);
} else {
console.log(data.clist[0].id);
console.dir(data.clist);
}
});
//create router object
var router = express.Router();
//export router
module.exports = router;
//home page
router.get('/', function(req, res) {
console.log('served homepage');
res.render('pages/home');
});
//--companies page--//
router.get('/company', function(req,res){
console.log('served companies page')
res.render('pages/company', {
clist: req.clist,
x: req.clen
});
});
Change your query.js like this,
//function to get companies list
exports.companyList = function(next){
r.table('company')
.run()
.then(function(response){
var list = {
clist: response,
clen: Object.keys(response).length
};
next(null, list);
})
.error(function(err){
console.log(err);
next(err);
})
};

Mongoose does not save anything to db with NodeJs

I have this very simple code that stores superhero name and power to database.
All connections work normally. When i ran mongod i used --dbpath C:/nodeprojects/sankarit/data. I have tried change the path like 50 times with different paths.
So my code sends nimi and supervoima (name, superpower) from client side and it tries to add them to database but literally nothing happens in db. When i write console.log("yay it works") on save function, it says that its working. And if i console log superhero it seems to work normally.
Here is client side:
$http.post("api/juttu", {nimi: "besthero", supervoima: "whiskey"}).success(function(response){
console.log(response.data);
}).error(function(){
console.log("Error")
})
Here is my server.js:
var express = require('express');
var path = require('path');
var app = express();
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
mongoose.set('debug', true);
// SANKARI SCHEMA
var Sankari = require('./app/models/sankarit');
// CONTROLLERIT
var testCtrl = require('./server/testCtrl');
app.use(bodyParser.urlencoded({ extended: true}));
app.use(bodyParser.json());
app.use('/public', express.static(__dirname + '/public'));
// DB conn
// I have tried with /test, /heros, /sankariKanta, /sankarit
mongoose.connect('mongodb://127.0.0.1:27017/test');
mongoose.connection.once('connected', function() {
console.log("Connected to database")
});
//PORTTI
var port = process.env.PORT || 8080;
// ROUTER
var router = express.Router();
app.get('/', function(req, res) {
res.sendFile('index.html', {root: __dirname});
});
app.post("/api/juttu", testCtrl.juttu);
app.listen(port);
Here is the testCtrl:
var Sankari = require("../app/models/sankarit");
module.exports.juttu = function (req, res){
// Tried also var uusiSankari = new Sankari(req.body);
var uusiSankari = new Sankari();
uusiSankari.nimi = req.body.nimi;
uusiSankari.supervoima = req.body.supervoima;
uusiSankari.save(function(err){
if(err){
console.log(err);
} else{
// This is always showing up
console.log("This is working!");
}
});
};
Also when i try console.log(req.body); It is working correctly.
Here is schema(sankarit.js):
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var SankariSchema = ({
nimi: String,
supervoima: String
});
module.exports = mongoose.model('Sankari', SankariSchema);
When i run the program, the mongoose debug thing says:
Mongoose: sankaris.insert({ __v: 0, _id: ObjectId("57ff0a649dbf169c15000001"), nimi: 'besthero', s
upervoima: 'whiskey' }) {}
So when i debug and console log everything the program does it seems to work like dream. I have made these MEAN stack tutorials like 5-10 and everytime database worked normally. This is first time i'm trying to make whole code by myself. I tried solve this whole night but i didn't get absolutely anywhere.
You forgot to use the Schema
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var SankariSchema = Schema({
nimi: String,
supervoima: String
});
module.exports = mongoose.model('Sankari', SankariSchema);

externalizing route.param() calls in Express.js

I want to extract some repetitive code into a single module in Node.js and Express.js
Together.js
var express = require('express');
var boom = require('express-boom');
var app = express();
var app.use(boom());
app.param('user', function(request, reply, next, id){
request.db.users.get(id, function(err, userInfo){
if (err) reply.boom.badImplementation(err);
else if (!userInfo || !userInfo.length) reply.boom.notFound();
else {
request.user = userInfo[0];
next();
}
})
})
app.get('/api/users/:user', function(request, reply){
reply.json(request.user);
});
app.listen(3000);
I have multiple routes I want to use this param conversion including: /users/:user, /api/users/:user, /checkout/:user/:barcode, etc. but each of the root routes (i.e. users, api, checkout) are in their own file and I am attaching them with app.use('/users', userRoutes);. As it is, I will have to put my user param conversion into EACH of these sub-route modules.
I would like to have an interceptors.js where I make all of the common param interceptor functions and only write them once. Here is an example of how I thought it would work.
app.js
var express = require('express');
var app = express();
app.use(require('./routes/interceptors'))
app.use('/users', require('./routes/users'));
app.use('/api', require('./routes/api'));
app.use('/checkouts', require('./routes/checkouts'));
app.listen(3000);
./routes/api.js
var express = require('express');
var api = express.Router();
api.get('/users/:user', function(request, reply){
reply.json(request.user);
});
module.exports = api;
./routes/interceptors.js
var express = require('express');
var boom = require('express-boom');
var interceptors = express.Router();
var interceptors.use(boom());
interceptors.param('user', function(request, reply, next, id){
request.db.users.get(id, function(err, userInfo){
if (err) reply.boom.badImplementation(err);
else if (!userInfo || !userInfo.length) reply.boom.notFound();
else {
request.user = userInfo[0];
next();
}
})
})
module.exports = interceptors;
There would of course be another file for each of checkout.js and users.js and they will be the same principal as api.js
When I do the above, the param interceptor is never run. No errors are throw that I can see.
Thank you all for any help you may provide,
Rhett Lowe
This can't be done.
Param callback functions are local to the router on which they are defined. They are not inherited by mounted apps or routers. Hence, param callbacks defined on app will be trigerred only by route parameters defined on app routes.
http://expressjs.com/api.html#app.param
Another approach you could do is to have a module with your interceptors and require it in your route files where necessary.
./routes/api.js
var express = require('express');
var api = express.Router();
var interceptors = require('./interceptors');
api.use('user', interceptors.user);
api.get('/users/:user', function(request, reply){
reply.json(request.user);
});
module.exports = api;
./routes/interceptors.js
exports.user = function(request, reply, next, id){
request.db.users.get(id, function(err, userInfo){
if (err) reply.boom.badImplementation(err);
else if (!userInfo || !userInfo.length) reply.boom.notFound();
else {
request.user = userInfo[0];
next();
}
})
})
module.exports = interceptors;

Categories