I have trouble implementing route mounting in express.js 4.13.3.
When I first install it, by default created in the app.js
var users = require('./routes/users');//get the "users" route
app.use('/users', users);//mount to "/users"
and the users.js route is like
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) {
res.send('respond with a resource');
});
module.exports = router;
Does not need to define router.get('/users'... because mounting took care of that in the app.js file.
But
When I try to do the same thing
in app.js I set
var upload = require('./routes/upload');
app.get('/upload', upload);//mounting (?)
the upload.js route is
var express = require('express');
var router = express.Router();
router.get('/', function(req, res) {
res.render('upload', {title: 'Photo upload'});
});
module.exports = router;
When I access localhost/users I get 404 error. The only way to fix this , is to define in the upload.js router, this router.get('/upload' instead of this router.get('/'. But that would not be mounting.
The difference I see is that the default code uses app.use('/users', users); and my code uses app.get('/upload', upload);. Is the verb (use/get) the only difference that causes the 404? And if so, why? Or is it something else?
Thanks
You are totally correct that the problem is caused because these to functions work differently. Below are the official API specifications for the functions.
app.use is for mounting a middleware
app.get is for defining (only) one route for a HTTP GET request
This example shows a middleware function mounted on the /user/:id path. The function is executed for any type of HTTP request on the /user/:id path.
app.use('/user/:id', function (req, res, next) {
console.log('Request Type:', req.method);
next();
});
This example shows a route and its handler function (middleware system). The function handles GET requests to the /user/:id path.
app.get('/user/:id', function (req, res, next) {
res.send('USER');
});
Related
I am trying to allow users to save and download static files. But have the files be accessible only for logged in (authorized) users.
routes/files.js
var express = require('express');
var router = express.Router();
/* Get files */
router.get('/*', isLoggedIn, function(req, res, next) {
console.log('get files called ');
express.static(path.join(__dirname, 'files'));
});
function isLoggedIn(req, res, next){
if(req.isAuthenticated()) return next();
res.redirect('/');
}
module.exports = router;
This works with any get request but not static files. They can be accessed with out being logged in.
app.js
var filesRouter = require('./routes/files');
app.use(express.static(__dirname));
app.use('/files', filesRouter);
I must be missing something simple - Thanks!!
Calling express.static(path.join(__dirname, 'files')); just returns a middleware function. It doesn't actually execute anything more than that. It doesn't serve any files until you call the function that it returns. You could get that middleware function once and then execute it conditionally, but it's easier to just do this:
/* Get files */
router.get('/*', isLoggedIn, express.static(path.join(__dirname, 'files')));
You should use express.static as a middleware.
And then to only allow authenticated users to access files, you coulld register isLoggedIn middleware before it. Please , see the code bellow, this should work.
var express = require('express');
var router = express.Router();
router.use(isLoggedIn); // this must come before express.static
router.use(express.static(path.join(__dirname, 'files')));
/* Get files */
router.get('/*', function(req, res, next) {
console.log('get files called ');
});
function isLoggedIn(req, res, next){
if(req.isAuthenticated()) return next();
res.redirect('/');
}
module.exports = router;
In app.js I have:
const routes = './routes/'
const usersRouter = require(routes +'users');
/*more code*/
app.use('/users', usersRouter);
In users.js, I have:
const express = require('express');
const router = express.Router();
/* GET users listing. */
router.get('/', function(req, res, next) {
res.send('respond with a resource');
});
module.exports = router;
My question: How does router.get('/') know to get the users file? Usually I would need to pass '/users' to router.get(. But with app.use('/users' in app.js, all I need is router.get('/') in users.js. In fact if I type router.get('/users' in users.js the program breaks.
Learning Express, and I could use explanation of how this works.
You have register the usersRouter as a middleware which will be executed when the Request URI is prefixed with /users an example will be https://localhost:3000/users/ or http://localhost:3000/users/subroute
// attach `usersRouter` as middleware
app.use('/users', usersRouter);
If in your users.js you have define route like this
router.get('/', (req, res) => {});
router.post('/users', (req, res) => {});
router.get('/:userId', (req, res) => {});
router.delete('/:userId', (req, res) => {});
module.exports = router;
You'll have this list of routes
GET => http://localhost:3000/users
POST => http://localhost:3000/users/users/
GET => http://localhost:3000/users/1
DELETE => http://localhost:3000/users/1
If the Request URI which you are trying to access is define in your express app, the handler will fallback to the Express buildin Error Handler.
So if you have define a router router.get('/users', ...) in the users.js file the application won't break as long you are trying to reach that router with http://...:../users/users.
Learn more about middleware
Learn more about Express routing
When you do this:
app.use('/users', usersRouter);
That already filters to send ONLY requests that start with /users to the router. It also strips off the /users from the start of the path so the router itself will do matching on the reduced path that has /users stripped from it which for /users will just be /. For a URL like /users/something, the router will match against /something.
Thus router.get("/", ...) will match the original URL of /users, but not /users/something.
The line
app.use('/users', usersRouter);
will make the users router handle requests prefixed with /users. The router in the users file therefore handles not /, but /users because you told your app to use that particular router for /users/*. In reality, this is simply a shortcut of doing router.get('/users') instead.
Based on Express docs, a middleware must run each time app is launched following this code:
var app = express();
app.use(function (req, res, next) {
console.log('Time:', Date.now());
next();
});
Well, trying to execute with the most simple possilbe example middleware never is excuted:
var express = require('express');
var middleware = require('./middleware');
var app = express();
app.use(function (req, res, next){
console.log('MIDDLEWARE');
next();
});
module.exports = app;
Middleware never runs.
Also tryed to make it working from a separated file, but never runs.
Thanks
Middleware are lunch when there are any request to the server.
Create a route and send a request to that, the middleware would be lunched.
Ups, seems to be they're launched when recieves a request. So using Postman it worked.
I've been having this issue where for some reason the Express route doesn't see my root get function. I've declared my app.js this way:
var index = require('./app/routes/index');
var app = express();
app.use('/', index);
Then in my index.js I have my definition this way:
var express = require('express');
var router = express.Router();
router.get('/', function(req, res, next) {
console.log('Enter root.');
});
router.get('/something', function(req, res, next) {
console.log('Enter something.');
});
Express routes into '/something' just fine, but couldn't see '/'. Anybody have an idea why it doesn't work? Thanks.
Modified based on new info:
If you're getting a 304 status back in the browser, that's because the browser has cached the GET request and the server is telling the browser that the page has not been changed so the browser can just use the cached copy.
You can make the page uncacheable by changing the headers the server sends with the request.
See Cache Control for Dynamic Data Express.JS and NodeJS/express: Cache and 304 status code and Nodejs Express framework caching for more info.
You show no exports in index.js so this line:
var index = require('./app/routes/index');
does not accomplish anything. index is an empty object and thus this:
app.use('/', index);
doesn't do anything and, in fact, may even cause an error.
Perhaps what you want is this:
var express = require('express');
var router = express.Router();
router.get('/', function(req, res, next) {
console.log('Enter root.');
});
router.get('/something', function(req, res, next) {
console.log('Enter something.');
});
// export your router
module.exports = router;
Then, index in your other file will be the router.
i am trying to execute below code after upgrading express4
// call the Router
var router = express.Router();
router.get('/test1', function(req, res, next) {
// doing more stuff
res.send('test test1 route')
});
// call our router we just created
app.use('/dogs', dogs);
but for some reason i am getting following error
this._router = new Router({
^
TypeError: object is not a function
at Function.app.lazyrouter
can someone help me to solve this problem ,Thank you in advance.
From the documentation:
var app = express();
app.route('/events')
.all(function(req, res, next) {
// runs for all HTTP verbs first
// think of it as route specific middleware!
})
.get(function(req, res, next) {
res.json(...);
})
.post(function(req, res, next) {
// maybe add a new event...
})
So try:
var router = app.route();
router.get('......
Or check the 3 to 4 upgrade guide.
Which says:
app.router has been removed and middleware and routes are executed in
the order they are added. Your code should move any calls to app.use
that came after app.use(app.router) after any routes (HTTP verbs).
app.use(cookieParser());
app.use(bodyParser());
/// .. other middleware .. doesn't matter what
app.get('/' ...);
app.post(...);
// more middleware (executes after routes)
app.use(function(req, res, next);
// error handling middleware
app.use(function(err, req, res, next) {});
I don't have a reputation to comment. Where and how did you declare your dog? Did you mean the following?:
// call the Router
var router = express.Router();
// call our router we just created
app.use(router);
router.get('/test1', function(req, res, next) {
// doing more stuff
res.send('test test1 route')
});
we can use this approach for routing in express4, when i am upgrading to express4 i didn't deleted express 3 folder, i tried deleting express3 folder from node modules and installing express4 than this worked fine