I'm very new to express and am running into issues getting proper routing set up. It's a homework assignment so the router file was already written, but there's a express.js file we're supposed to fill in to make calls to the api whenever a get/put/post/delete request is made at that address. The router file is set up like this:
var listings = require('../controllers/listings.server.controller.js'),
getCoordinates = require('../controllers/coordinates.server.controller.js'),
express = require('express'),
router = express.Router();
/*
These method calls are responsible for routing requests to the correct request handler.
Take note that it is possible for different controller functions to handle requests to the same route.
*/
router.route('/')
.get(listings.list)
.post(getCoordinates, listings.create);
/*
The ':' specifies a URL parameter.
*/
router.route('/:listingsId')
.get(listings.read)
.put(getCoordinates, listings.update)
.delete(listings.delete);
/*
The 'router.param' method allows us to specify middleware we would like to use to handle
requests with a parameter.
Say we make an example request to '/listings/566372f4d11de3498e2941c9'
The request handler will first find the specific listing using this 'listingsById'
middleware function by doing a lookup to ID '566372f4d11de3498e2941c9' in the Mongo database,
and bind this listing to the request object.
It will then pass control to the routing function specified above, where it will either
get, update, or delete that specific listing (depending on the HTTP verb specified)
*/
router.param('listingId', listings.listingByID);
module.exports = router;
And the express.js file is like this:
var path = require('path'),
express = require('express'),
mongoose = require('mongoose'),
morgan = require('morgan'),
bodyParser = require('body-parser'),
config = require('./config'),
listingsRouter = require('../routes/listings.server.routes'),
getCoordinates = require('../controllers/coordinates.server.controller.js');
module.exports.init = function() {
//connect to database
mongoose.connect(config.db.uri, {useMongoClient: true});
//initialize app
var app = express();
//enable request logging for development debugging
app.use(morgan('dev'));
//body parsing middleware
app.use(bodyParser.json());
/* server wrapper around Google Maps API to get latitude + longitude coordinates from address */
app.post('/api/coordinates', getCoordinates, function(req, res) {
res.send(req.results);
});
This is the part I can't figure out:
/* serve static files */
app.get('/listings', listingsRouter, function(req, res){
res.send(req.get('/'))
});
/* use the listings router for requests to the api */
/* go to homepage for all routes not specified */
return app;
};
I'm just not sure how to use the routes in the listingsRouter file with the req and res objects and I can't find any examples of a program set up like this to help. Any assistance would be appreciated.
Change following
app.get('/listings', listingsRouter, function(req, res){
res.send(req.get('/'))
});
To
app.use('/listings', listingsRouter);
Express Router. Scroll down to express.Router section for complete info.
Hope this helpls.
Related
Hello guys so i have this two variables i am requiring them for every route i have so i want to globalize them and just add them to the app.js but when i do that it didn't work.
var express = require('express');
var router = express.Router();
i tried to addd them in to my separate file config.js and then i require it in my route and assign it to variable and use it but it is not working.
my config file look like this
/**
* Module dependencies.
*/
var express = require('express'),
favicon = require('serve-favicon'),
logger = require('morgan'),
bodyParser = require('body-parser'),
methodOverride = require('method-override'),
errorHandler = require('errorhandler'),
path = require('path');
module.exports = function() {
var app = express();
var router = app.Router();
return app;
}();
i get this error all the time :
throw new Error('\'app.router\' is deprecated!\nPlease see the 3.x to 4.x migration guide for details on how to update your app.');
TLDR: Your router variable is an instance of Router, and should to be initialized inside each of your route files. I can appreciate trying to be as DRY as possible, but doing it this way will not work the way you expect it to. You can save a bit of typing by writing it this way:
var router = require('express').Router();
The longer explanation is that use multiple routes, you need a router for each route. This is to help break up the whole path associated with a request (i.e. /bar/foo/baz) into more manageable chunks.
Let's say your path can start with either /cats or /dogs. In the file where you declare all your middleware, you could write:
var catRoute = require(./routes/cats)
var dogRoute = require(./routes/dogs)
app.use('/cats', catRoute)
app.use('/dogs', dogRoute)
Then, inside cats.js:
var router = require('express').Router();
router.get('/whiskers', (req, res) => {
res.send('Cat whiskers!')
}
module.exports = router;
What this does is tell the app if it gets a path starting with /cats, use the cats route, which is just another piece of middleware. Within the route itself, we don't have to specify /cats/whiskers, only /whiskers because app is only passing down the part of the path after /cats to the cats.
You can nest as many routers as you want. Check out this article for a good example of how to do that.
Hypothetically, you could use only one router
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.
I have developed an API using Node.js + Express JS and i use token-based authentication.
I used two differents routers in this api, userRoute (/USER) and postRoute (/POST). The postRoute can be used within authentication but userRoute needs the token.
To solve that i use a router middleware for userRoute but it interferes with portRoute
This is the code:
...
var postRoute = express.Router();
var userRoute = express.Router();
// Route middleware to verify a token
userRoute.use(function(req, res, next) {
security.checkToken(req,res, next);
});
userRoute.route('/users')
.get(userCtrl.findAllUsers)
.post(userCtrl.addUser);
postRoute.route('/posts')
.get(userCtrl.findAllPosts)
.post(userCtrl.addPost);
app.use(userRoute);
app.use(postRoute);
...
If i try to access '/posts' the servers checks the token and does not let me in. I know if i change the order of app.use it works, but i dont understand why works in this way if i am using "Router Middleware".
Someone knows?
This happens because if the express router implementation, you will be able to understand it quite easily if you have a look at it. Here is the path: node_modules/express/lib/router/index.js. Every time that you call the Router(), like in your case
var postRoute = express.Router();
var userRoute = express.Router();
this function will be invoked:
var proto = module.exports = function(options) { ... }
and it is true that there is a different router instance that is being returned every time. The difference is in the way that the use is registering the middlewares. As you see the use it is registered against the proto.use
proto.use = function use(fn) { ... }
this means that the middleware that you register there they will be registered for every instance of the router that you define.
In my NODEjs ( using Express ) application, I want to use Country Code inside routes.js but I am unable to access localstorage inside the routes.js
Please provide some solution.
LocalStorage is only available in browsers on the Window object.
The Window object is not available server side.
MDN
Following your comment, you could implement a route in your express application which takes the IP as part of the body.
For this to work you will need body-parser middleware. Example application:
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var server;
app.use(bodyParser.json());
app.get('/api/ip', function (req, res) {
res.send(req.body.ip);
});
server = app.listen(3000);
This would return the posted IP.
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