Two apps in expressjs - node.js

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')
);

Related

Nodejs have an optional extra path in URL

I'm developing part of a system where we have two applications sharing the same domain so nginx makes exampleurl.com go to one application and example.com/admin/* go to the second.
The /admin/* part is going to a NodeJs app using express.
Is there an elegant way of making sure that node can add in the /admin without having to do
app.get('/admin/endpoint', ...)
?
you can use http://expressjs.com/fr/api.html#router
var router = express.Router();
router.get('/', function(req, res) {
res.send('One page in admin website');
});
// router.get('/adminWebsite'); // idem for all routes(you always use this router)
app.use('/admin', router);
you would would to use routers (preferably) but you can also create another express app. using different Apps allow you to have more global middlewear control whereas using different routes mean that they share the same express instance.
var express = require('express');
var admin = express(); // <- this is now your admin application
var app = express(); // <- this is your main applicaiton regular users
//you will need to set up middlewear like body-parser and stuff for both of them now
//but it allows you to use different logging and authentication system or w.e you
//want
//once everything is done you can 'MOUNT' virtually the admin app to the regular app
app.use('/admin', admin); //<- this will nest apps together but allow the sub-app admin
//to be it's own instance.
//app.js
const admin = require('admin'); //you admin module (where you routes wiil be)
app.use('/admin', [functions... example authCheck], admin);
//index file of admin module
`var express = require('express');
var router = express.Router();
router.use(function authCheck(req, res, next) {
//check if user is logged
});
router.get('/main', require('./main').get);
module.exports = router;`
//main.js
`exports.get = function(req, res, next){
res.render('admin/admin', {
title: "Main panel"
});
};`
and now you can access site.com/admin/main

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.

Encapsulate Express Routers

Is it possible to create different routers using Express.Router that don't share middleware?
To me it seems that Express.Router uses a singleton, so no matter what I try, the middleware gets attached to all routers. So, without having to create multiple instances of the Express app, is there a way to achieve the following:
Create mutliple routers
var router_a = Express.Router();
var router_b = Express.Router();
Give each router unique routes and middleware
router_a.use(function(req, res, next){
console.log('Only works on router_a!');
});
router_a.get('/', function(req, res){
console.log('Only works on router_a!');
});
router_b.use(function(req, res, next){
console.log('Only works on router_b!');
});
router_b.get('/', function(req, res){
console.log('Only works on router_b!');
});
Attach each route to a custom url namespace
app.use('/a', router_a);
app.use('/b', router_b);
Is there a straight forward way to achieve this? After reading through the docs on the Router I don't see anything that suggests such is possible.
The one thing I see missing from your code is the call the next() in your middleware. If I add that to your code, it works perfectly fine for me.
The /b middleware is only called if the route starts with /b and same for the /a middleware with /a routes. And, to finish your code, you also have to send a response in your .get() handlers.
Here's the specific code I just tested:
var express = require('express');
var app = express();
var server = app.listen(80);
app.use(express.static('public'));
var router_a = express.Router();
var router_b = express.Router();
router_a.use(function(req, res, next){
console.log('.use() - Only works on router_a!');
next();
});
router_a.get('/', function(req, res){
console.log('.get() - Only works on router_a!');
res.send("router a, / route");
});
router_b.use(function(req, res, next){
console.log('.use() - Only works on router_b!');
next();
});
router_b.get('/', function(req, res){
console.log('.get() - Only works on router_b!');
res.send("router b, / route");
});
app.use('/a', router_a);
app.use('/b', router_b);

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");
});

Creating a Modular REST API in ExpressJS

I'm having some trouble creating a RESTful API in Node/Express. In the app I'm building, a user has many messages, and messages belong to users. I need to be able to make an HTTP requests to retrieve all messages by a particular user. Here's the basic structure of the app, starting with the basic server, which delegates routing to a file called 'config/middleware.js'.
//server.js
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
require('./config/middleware.js')(app, express);
var port = process.env.PORT || 8080;
app.use(bodyParser.json());
app.use(express.static(__dirname + '/../client'));
app.listen(port);
This is the middleware file where we send requests to the appropriate router. A request made to 'users/5/messages' would get routed to the messages router, and a request made to 'users/5' would get routed to the users router.
// config/middleware.js
module.exports = function(app, express) {
var usersRouter = express.Router();
var messagesRouter = express.Router();
app.use('/users/:userId/messages', messagesRouter);
app.use('/users', usersRouter);
require('../routers/users')(usersRouter);
require('../routers/messages')(messagesRouter);
};
This is the messages router. If a get request is made to '/users/5/messages', I want the getAllMessages function to be run, which should return all messages by the user with userId 5.
// routers/messages.js
var messagesController = require('../controllers/messages');
module.exports = function(app) {
app.get('/:messageId', messagesController.getMessage);
app.get('/', messagesController.getAllMessages);
};
The problem is that the getAllMessages function doesn't have access to the 'userId' parameter (with value of 5), which is required in order to make an appropriate query to the database. The getAllMessages function in the controller expects the userId to be stored on req.params.userId. Is there any way to get the userId of 5 to be present on the req.params object inside the getAllMessages function?
The req.params are not passed down the route chain. To do so, you could do something like
In server.js, create a key on req. This will pass on your data between routes. Do this before mounting the routes.
app.use(function (req, res, next) {
req._data = {};
next();
});
In config/middleware.js,
module.exports = function(app, express) {
var usersRouter = express.Router();
var messagesRouter = express.Router();
// attach usedId
app.use('/users/:userId/messages', function (req, res, next) {
req._data.userId = req.params.userId;
next();
});
// mount the router
app.use('/users/:userId/messages', messagesRouter);
app.use('/users', usersRouter);
require('../routers/users')(usersRouter);
require('../routers/messages')(messagesRouter);
};
This way, you would have access to req._data.userId in routers/messages.js.
Side note: A better way to structure the routes would be to use something like, (read shameless plug), https://github.com/swarajgiri/express-bootstrap/blob/master/web/routes.js
You can use app.locals or res.locals to pass some datas.
There is a good explanation about locals.
An usage sample:
app.locals.userid = req.params.userId; //binding userid
app.locals.userid // => '5'
OR: put a global variable.
user_id_tmp = req.params.userId;
Now this is become global variable in app. So you can call user_id_tmp variable from anywhere.
I was looking for same.
Here is modules app example on github and auther site
Also we can change or update structure base on our requirements

Resources