I have site stub, where routing is set in 2 places.
First in app.js:
...
var index = require('./routes/index');
var users = require('./routes/users');
...
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', index);
app.use('/users', users);
...
something is set with use. Next inside referred scripts, like index.js:
var express = require('express');
var router = express.Router();
var fs = require('fs');
var path = require('path');
var config = require('../config');
/* GET home page. */
router.get('/', function(req, res) {
var data = {};
...
Suppose I wish to use infromation from Express Routing doc. Where I should put the routing for, say, /users/:userId/books/:bookId?
In docs, get is called against app, while in my stub, get is called against router and in two-step manner.
Where to hook?
In docs get is called against app because they set their endpoints in app.js file. In your index.js you return the router from the file with module.exports = router;, which is app's router. Now in your app.js file says
app.use('/', index);
app.use('/users', users);
These are the routes. You are saying that all the endpoints which are in index file are starting with / and the endpoints which are in users file are starting with /users.
So the route /users/:userId/books/:bookId must be in users.js file like this
router.get('/:userId/books/:bookId', function(req, res, next) {
// do something
});
If you want to handler this route - /users/:userId/books/:bookId, then you need to write following handler in your routes/users.js file.
router.get('/:userId/books/:bookId', function(req, res) {
var data = {};
});//get route
Basically, in app.js you are categorising url's based on its first part e.g. users. So, all your routes that start with /users will be handled by your routes/users.js class. All other routes will be handled by routes/index.js, because that is defined to handle / (there is no /users, /admin etc. so all routes that are not handled by users.js can be handled in this.)
Also, in these route handler files, you define a router object, add all route handlers to it and export it at the bottom. So when you are in these files, you need to use router and in app.js you can directly use app.get() etc.
Related
I was learning Express in Node.js and came across Router() allowing us to modularize our routes. But than I found this code:
// we'll create our routes here
// get an instance of router
var router = express.Router();
...
// route with parameters (http://localhost:8080/hello/:name)
router.get('/hello/:name', function(req, res) {
res.send('hello ' + req.params.name + '!');
});
// apply the routes to our application
app.use('/', router);
What confused me is that why we need to use app.use('/', router); to apply the routes. That is, what if we use app.get('/', router);
I am giving you a simple code example to make you understand the use of express.Router(). Yes you are right that it helps in modularization. Actually it makes our main app.js file clean from all the routes. We just put all those routes based on their purposes in different files and require them when needed.
so suppose I have two files app.js and register.js
// app.js file's code goes here
let express = require("express")
let app = express()
let register = require("./routes/register")
app.use(register) // This will tell your app to import all those routes which are in register
// register.js file's code goes here
let express = require("express")
let router = express.Router()
router.get("/register", callback_function);
router.post("/register", callback_function);
module.exports = router;
So basically what I am trying to show is your register.js can contain all types of HTTP requests(GET, POST, PUT,...) and when we use app.use(register) this will handle all those routes. app.get("route_path", callback_function) is only for handling get requests to that path.
Router is just a middleware of it's own. If you use app.get('/', router) you will use the router just for GET requests. Using use channels all requests there.
When app.use is used then it handled all the HTTP methods, but when app.get is used it takes just GET method.
Added advantage to app.use is that route will match any path that follows its path immediately with a /.
For example:
app.use('/v1', ...)
will match /users, /users/accounts, /users/accounts/account-id, and so on.
I'm new to NodeJs and express. My goal is to have a separate route file that contains all my application routes. So I created a file called routes.js. The content looks like this:
const express = require('express');
const router = express.Router();
router.get('auth/register', require('./controllers/auth/register'));
module.exports = router;
In my main file, I require the file with this line. The app variable contains my express instance.
app.use('/', require('./routes'));
If I call http://localhost/auth/register in my browser, I'm always running into a 404 Not Found error. When I define the route directly in the main file with app.get('/auth/register', require('./controllers/auth/register')); it works well. There are no errors in my console.
Has anyone an idea why my sperate route file does not work? Thank you for your help!
Traditionally, I do the following which is to pass the express instance into your routes module:
once I have instantiated my express instance called app
app.js
require('./routes.js')(app);
routes.js where registerUser us the function to call when the route is matched
module.exports = (app) => {
app.route('/auth/register')
.post(registerUser);
}
You want to pass app into your routes file. A good pattern for this is to import your routes in your main file, like const routes = require('./routes');
In routes, you can define all of your routes like so:
module.exports = (app, router) => {
router.route("/").get()
router.route("/something_else").post()
app.use("/api", router)
...
};
This way, in your main file, you can do: routes(app, router) and have access to app and router inside your routes.js.
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
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.
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