break routes out of Node/Express server, but router is undefined - node.js

I'm trying to break the routes out of my Node server because it's getting a little cluttered. I followed a pattern I saw in a tutorial server and made a file routes/routes.js which looks like this:
var router = require('express').Router()
// routes in here
module.exports = router
I added this line to my server
app.use(require('./routes/routes'))
but my server won't start and gives the error
router.get('/', function (req, res, next)) Cannot call method 'get' of undefined
I checked the express docs (version 3.16.3), but I couldn't figure out why router is undefined and can't call 'get'

I generally have a routes config and I just require that.
// config/routes.js
module.exports = function (app) {
app.get('/', get.stuff);
app.post('/api/:id', create.stuff);
}
Now in our server, we just require the routes.js file, and send app to it
// server.js
var app = express(),
server = http.createServer(app).listen(app.get('port'), function() {});
require('./config/routes.js')(app);

Related

Node.js with express routing and sub routing

I am playing with node.js and I don't quite understand why something I set up is working in one instance but if I make a slight change it will not work in another instance.
in my app.js I have
app.use('/musicplayer', require('./routes/music/index'));
in my music\index.js I have
var express = require('express');
var router = express.Router();
router.use('/users', require('./users'));
module.exports = router;
in my users.js I have this - working version
var express = require('express');
var usersRouter = express.Router();
var sqllite3 = require('sqlite3').verbose();
usersRouter.get('/login', function(req, res, next) {
res.render('music/login', { title: 'Express' });
});
module.exports = usersRouter;
But I would like to encapsulate the routes I am defining into another function like this not working this just hangs the page.
Modified version of my users.js not working
var express = require('express');
var usersRouter = express.Router();
var sqllite3 = require('sqlite3').verbose();
var router = function () {
usersRouter.get('/login', function (req, res, next) {
res.render('music/login', {title: 'Express'});
});
return usersRouter;
}
module.exports = router;
In the console I can see it comes in tries the get and nevers gets routed I see this "GET /musicplayer/users/login - - ms - -".
I have even put a console.log right before the return in the anonymous function I created to know it is getting in there and that I am hooking the pathways up right from the parent routes. And I do hit that log action to the screen.
Any help or tips would be appreciated:)
PS in case you are wondering I am trying to separate out apps for different development work I want to play with. So that is why I am doing the sub routing with musicplayer/index.js instead of just putting everything in the app.js for declaring of my main routes.
Router.use() expects an instance of another Router. However your (non-working) module only returns a function.
Use this in your index.js to fix the issue:
router.use('/users', require('./users')());

Express route not returning

Probably a silly mistake but I cannot see why I'm not getting a response from a GET request.
This is part of my server file located in the root:
//server.js
...
var serverRoutes = require('./server/routes');
app.use('/server', serverRoutes);
...
and my routes file:
//server/routes/index.js
var express = require('express');
var router = express.Router();
module.exports = function() {
router.get('/test', function(req, res, next){
console.log("HIT");
res.status(200).send("OK");
});
return router;
}
Everytime I navigate to /server/test in my browser it just stalls. Nothing is logged in the terminal and no "OK" response is received in the browser - what am I missing?
Your serverRoutes module exports a function that returns a router. You need to invoke it in order to pass the Router instance it returns to app.use:
app.use('/server', serverRoutes());
Otherwise, express is going to treat your exported function as a middleware, which will cause the app to hang since it does nothing with the response passed to it.

How can I still use a router in node express and still have a wildcard and params?

So basically I want my code being able to go mywebsite.com/username and itll take them to their profile.
My app.js has -
var user = require('./routes/user');
app.use('/*', user);
and then in my user.js I have
router.get('/:username', function(req, res) {
console.log('the user name', req.params.username);
})
If I change router.get to just router.get('/') my console.log logs out undefined and if I leave it as router.get('/:username') I get a 404.. I also tried doing app.use('/:username', user) as well but that still didn't work.
You should't need to have a wildcard like you do on app.use
Try something like this.
Also see the express router documentation http://expressjs.com/en/guide/routing.html
// Required Moduiles
var express = require('express');
var router = express.Router();
var app = express();
// Add route to get
router.get('/:username', function(req, res) {
res.status(200).send(req.params.username)
})
// Add username
app.use('/', router)
// Start express server
app.listen(3030);
Update -
Just using app.use(router) would do the same thing if all your routes are going to be contained in this new router instance / middleware you are creating in a separate file.

how to create a nodeJS module with expressJS

I'm making a nodeJS module, and I want to use expressJS as a framework for it.
I'm trying to see, how I could go by, including a function inside and app.get(); and call it via another file, such as the actual app.
var express = require("express");
var app = express();
app.get("/", function (req, res) {
exports.type = function (text) {
console.log(req.ip);
console.log(text);
}
});
now when I use this, and i call it on the actual app like:
var web = require("directory_to_file");
var express = require("express");
var app = express();
var http = require("http").Server(app);
app.get("/", function (req, res) {
web.type("Hello, world");
});
http.listen(10022, function () {
console.log("server is up");
});
I get an error:
TypeError: Property 'type' of object #<Object> is not a function
anyone know a way to make it so I can call the function?
There are generally two things you want to export as a module - an API and a Middleware. The classic example of middleware is an authentication module. To do the middleware, just export the middleware. I tend to do a little more than that so I can configure the middleware later. Something along the lines of this:
module.exports = exports = function(config) {
// Do something with config here
return function(req, res, next) {
// your middleware here
};
};
You can then use your middleware in your main program like this:
var app = require('express')(),
mymodule = require('./mymodule');
var config = {}; // replace with whatever config you need
app.use(mymodule(config));
app.listen(process.env.PORT || 3000);
To implement an API, you will create a Router object, then attach your routes to the Router object. You can then "mount" your router in your main program. For example, you could have a file called 'myroutes.js' with the following contents:
var express = require('express'),
myroutes = express.Router();
myroutes.get('/foo', (req, res) => {
res.status(200).type('application/json').send({ myparam: 'foo' });
});
module.exports = exports = myroutes;
Have the following in your main program:
var app = require('express')(),
myroutes = require('./myroutes');
app.use('/api', require('./myroutes'));
app.listen(process.env.PORT || 3000);
Here, in 'myroutes.js', I'm defining a sub-route of /foo and then in the main program, I'm mounting that on /api - so I would access /api/foo to access that API.
In your directory_to_file you are only exporting on app.get('/') which will never be called.
You could add in your directory_to_file the following code
var express = require('express');
var router = express.Router();
router.get('/', function(req, server) {
console.log(req.ip);
});
module.exports = router;
And in your main file you could use app.use('/', web)
A short explanation:
You are creating a new express app / config in your directory_to_file file which won't be launched or used. So your app.get event won't be fired once.
That's why web.type is not a function. You are not exporting anything.
Use the way I provided. This is a commonly used method.
You could call the code I provided a "route". Create multiple routes / route files and include them in your main method.
Your code just looks confused. If I understand you correctly, what you are really trying to do (at least in Node/express terminology) is write your own middleware.
Express is designed with this in mind and it's pretty straightforward e.g.
ipLogger.js
module.exports = function(req, res, next) {
console.log(req.ip);
next();
}
app.js
var http = require("http")
, express = require("express");
, app = express()
, server = http.Server(app)
, ipLogger = require("./ipLogger.js");
app.use(ipLogger()); // log IP of all requests
// handle routes
server.listen(10022, function() {
console.log("server is up");
});

Two apps in expressjs

I am building an app with express js which will have different clients like web and mobile. I didnt want to use one app for both as some middleware would be additional burden. For say like session middleware. So is it possible for one project to have two apps. And how would it work?
The app object that you make in express is a function(req,res,next) that is suitable for Express's own middleware chains. So you can use app.use to send requests matching a leading path fragment to an app defined elsewhere.
Docs: http://expressjs.com/api.html#app.use
$ npm install express
//mobile.js
var app = require('express')();
app.get('/', function(req, res){
res.send('Mobile Route')
});
module.exports = app;
//desktopApp.js
var http = require('http');
var express = require('express');
var desktopApp = express();
var mobileApp = require('./mobile.js');
desktopApp.use('/mobile', mobileApp)
desktopApp.use(desktopApp.router);
desktopApp.use(express.errorHandler());
desktopApp.get('/', function(req, res){
res.send('Desktop Route')
});
desktopApp.get('/mobile', function(req, res){
// Because Express respects the order that you set up the middleware chain,
// the mobileApp `/mobile` route gets first dibs to send a response or next()
res.send('Inaccessible Desktop Route')
});
desktopApp.get('/mobile/foobar', function(req, res){
// When mobileApp can't find any suitable route matching this path, it gives
// up, and desktopApp continues to pass the request down the middleware stack.
// It ends up matching this route, where we send a response
res.send('Desktop Route')
});
http.createServer(desktopApp).listen(3000, function(){
console.log('Listening on 3000');
});
// Results
$ curl localhost:3000/
Desktop Route
$ curl localhost:3000/mobile/
Mobile Route
See the vhost example on the express github repository.
You can have a "main" app, which routes the requests to one app or another. You should write a middleware to establish the conditions where one app or another are requested. express.vhost is a good example, but maybe you need other checks than the domain one.
main-app.js
(The file called to start the server.)
// load dependencies
var main = express();
main.use( express.vhost( 'mobile', require( './the-mobile-app' ) );
main.use( express.vhost( '*', require( './the-web-app' ) );
main.listen( /*...*/ )
the-mobile-app and the-web-app.js
var app = express();
//
// setup your application conf, middleware, and routes
//
module.exports = app;
I wanted to share a different approach that I used in a project recently:
function renderAppropriate(template1, template2){
return function(req, res){
if(req.session && req.session.mobileOn){
res.render(template1);
} else {
res.render(template2);
}
};
};
app.get('/', function(req, res, next){
// do some stuff
next()
}, renderAppropriate('someMobileTemplate', 'someDesktopTemplate')
);

Resources