So I have what is probably a noob question about routing in express and node.js
I have a middleware that loads a JSON file that contains all of the paths and configuration for these paths. The configuration file looks something like this
module.exports = {
"/account" :{
template: "dashboard/account",
page_title: "My Account",
// more path configs....
},
"/account/:id/users" : {
template: "dashboard/account/account-users",
page_title: "Account Users",
// more path configs....
}
}
And the middleware method that gets called in my app server when the app is created
app.use(middleware.getRouteConfig);
looks like this
var routeConfig = require('../config/route-config'); // path to the JSON above
getRouteConfig: function (req, res, next) {
req.config = routeConfig[req.path];
next();
},
And finally my express route looks like this
app.get('/account/:id/users', function(req, res){
// Get the users
//
});
Now lets say I go to /account/12345/users
Express noticed that the route has the :id in the middle and goes to that route. However my middleware then will try to load the config for that route and it can't find /account/12345/users in my JSON config file.
So my question is how do I load that route configuration using my dynamic :id path variable and get the configuration from the JSON file. Thanks in advance
Implement json parser using GSON SDK of Google.
You will found sample code from : http://www.javacreed.com/gson-deserialiser-example/
For json string validator : http://jsonlint.com/
Related
New to Express. Want to implement an MVC pattern in Express and substitute routes folder with controller folder. I found this code, which actually works, but I don't really understand what it does:
var fs = require('file-system');
fs.readdirSync('controllers').forEach(function (file) {
if(file.substr(-3) == '.js') {
const route = require('./controllers/' + file);
route.controller(app);
}
})
The readdirSync reads the content of the folder 'controllers' and for each file it founds it does something that I don't understand:
if(file.substr(-3) == '.js') //checks if the end of the file is .js but why?
const route = require('./controllers/' + file); //don't understand this
route.controller(app); //don't understand this
Could you please help with this?
Thank you.
The example you follow comes from this blog entry by Tim Roberts. The example controller demonstrates what is it all about:
var mongoose = require('mongoose')
var Video = require('../models/user');
module.exports.controller = function(app) {
app.get('/signup', function(req, res) {
// any logic goes here
res.render('users/signup')
});
app.get('/login', function(req, res) {
// any logic goes here
res.render('users/login')
});
}
If you save this example controller in the controllers folder under whatever.js, all it does it exports a function, controller, that takes the express app as an argument and adds a couple of custom routes to the app.
Then, the main module scans all such files under the controllers folder and first uses the require function to load the module:
const route = require('./controllers/' + file);
After above line, the route contains a reference to the module that contains this controller function.
This
route.controller(app);
just calls the function exported from the module, passing the global app as an argument.
This way you can easily extend your app just by creating separate .js modules under controllers folder, that follow the same convention (export the controller function).
My folder structure is public-js-color.js and the ejs file is views-index.ejs
How do I pass a variable from the color.js file into the index.ejs file so I can display it to the user. Please forgive me if this is simple, just learning node and google has been no help.
when you define your express route and call render you want to pass to the view as the second parameter.
var variablesToPass = {
homie: 'who is your homie?'
};
app.get('/', function(req, res) {
return res.render('index', variablesToPass);
});
You will be able to render homie on your ejs home template by typing <%= homie %>
Also if you would like the variables to be available across your entire application a useful middlware function you could create is.
app.use(function(req, res) {
res.locals.homie = "I'm a homie thats available everywhere";
});
I have a sails app and the routes,static assets associated with the app are served from root and it works fine. I would like to add a express middleware so i could serve the routes and static assets in a specific path.
In order to serve the static assets i used the below inside the customMiddleware function in config/http.js,
app.use('/my/new/path', express.static(path.join(__dirname, '../client', 'dist')));
With the above in place i was able to load the static files both from the root as well as from the /my/new/path.
Now when it comes to route i'm not sure how to handle the sails route to load via express middleware using app.use, for example the home route defaults to '/' in my config/routes-client.js, instead of altering the route there i would like to use something like below which we normally use for a typical node/express app,
app.use('/my/new/path', routes); --> where routes is my server routes
Is there a way to add a express middleware to serve sails route on a specific path?
I'm not sure why you'd want to have a prefix added automatically to your custom routes rather than just adding the prefix directly to the routes in the config/routes.js (or config-routes-client.js) file, but here goes:
// config/http.js
middleware: {
reroute: function (req, res, next) {
// Set the prefix you want for routes.
var prefix = '/foo/bar';
// Create a regex that looks for the prefix in the requested URL.
var regex = new RegExp('^' + prefix + '(/|$)');
// If the prefix is found, replace it with /
if (req.url.match(regex)) {
req.url = req.url.replace(regex, '/');
}
// Continue processing the request.
return next();
}
}
Make sure you add reroute to the middleware.order array in config/http.js. Incidentally, this will take care of static files as well.
This is how I do it...
Inside http.js
var express = require('express');
module.exports.http = {
customMiddleware: function (app) {
app.use('/docs', express.static(path.join(sails.config.appPath, '/docs')));
},
... rest of the http.js code...
}
Of course in this example im serving docs folder from root of my app on route /docs... You addapt to your logic...
I have an app where I am trying to remove the hashbang ( ! and #) prefixes for my routes, but still have people be able to use bookmarked routes. For the most part I have been able to get it work with html5Mode set to true, but there are a few cases where it is not working. Here is how I have my server configured:
var router = require('./router')(app);
app.use(express.static(path.join(__dirname, '../client')));
app.get('*', function (req, res, next) {
res.sendFile('index.html', {root:'../client/app/'});
});
router in this case looks like this:
var express = require('express');
var router = express.Router();
var Products = require('../../database').Products;
router.get('/:flavor', function (req, res) {
var flavor = req.params.flavor;
Products.findOne({flavor:flavor}, function (err, product) {
if (err) {
throw err
}
res.json(product);
});
Getting the flavor routes, is one case where this setup does not work. If someone directly types into the browse, mysite.com/lemon they receive the JSON data back, only (no template or anything). Normally this is used by the angular app, (which would typically make the request to /lemon and implement it into the template). However, if I move the router below the app.get('*'), then any request made by Angular for the data is returned with the entire index.html page. How can I make it so that a direct request by the browser for a route that normally returns JSON sends the index file?
I'm having trouble with this script
// App.js ( shrink )
var controller = require('./controller');
app.get('/', controller.index);
app.get('/home', controller.home);
// /controller/index.js
var meta = {
title: 'index',
description: ''
}
exports.index = function(req,res){
res.render('index', {
meta: meta
});
}
// /controller/home.js
var meta = {
title: 'glibet',
description: ''
}
exports.home = function(req,res){
res.render('home', {
meta: meta
});
}
Its returning me this Error: "Error: Route.get() requires callback functions but got a [object Undefined]"
Strangely enough it works just fine if i let app.get('/', controller.index); alone without the home route
I've tried a couple of corrections/alternatives in the code maintaining the system its way of invoking controller/files but it doesn't seem to fix the code, i will really appreciate any help.
PS: I'm trying to avoid setting a variable to each controller file, avoiding something like this code;
var homeController = require('./controllers/home');
var userController = require('./controllers/user');
app.get('/', homeController.index);
app.get('/login', userController.getLogin);
When you require ./controller, Node first looks for a file called controller. Failing that, it looks for a file called index.js inside the directory controller.
You are not requiring every file in a directory by using require() in this manner.
You could use a plugin such as require-dir for this purpose. However, my recommendation would be to require each file separately, so that you know exactly what you are making available to your page-- this prevents side effects where you accidentally leave a file in your routes directory that you didn't want required by your main application controller.
You are trying to require a directory of js files as an object. If you want to keep all of your controller files separate but have them represented in one object in your app, you could do something like this:
// /controller/controllers.js
var home = require('./home');
var index = require('./index');
module.exports = {
home: home.home,
index: index.index
}
By requiring './controller/controllers' you could keep all of your controller endpoints organized in different files while accessible in one object.