NodeJS: How to add routes afterwards (after middleware) - javascript

i'm currently working on a project with node.js.
I stucked at a specific problem. After adding all routes
with express (app.get("..", func)) I end up with a middleware that
catches all requests and redirects to a 404-page.
The thing is now, when I add a route afterwards during server run, the middleware
doesent care about the new route.
example:
app.get("/home", function(_, res) {
res.send("home");
})
app.get("/faq", function(_, res) {
res.send("faq");
})
app.use(function(_, res) {
res.send("404");
});
// e.g. 10 min later..
app.get("/team", function(_, res) {
res.send("team");
})
So i can access /home and /faq but after 10 min requesting the page /team, i am redirected to the 404 page.
Does anybody know a solution ? Im quite new to nodejs..

Although adding routes dynamically doesn't sound like a good idea, here's a workaround: add an (empty) Router instance right before the 404 handler, and add the new routes to that router instead of to app:
let router = express.Router();
app.use(router);
app.use(function(_, res) {
res.send("404");
});
// e.g. 10 min later..
router.get("/team", function(_, res) {
res.send("team");
})

Related

Node API: Paramterization in routing

I'm trying to build up an api for my website. However I kind of struggle with the route params.
I have two routes for now:
const route1 = require('./routes/route1')
const route2 = require('./routes/route2')
app.use('/route', route1)
app.use('/route/:id/details', route2);
The first route works perfectly fine. Within the first route, I check for the ID param as well as I do gets like
Code in route1
router.get('/:id', async (req, res) => {
...
})
I can easily check for the ID as a paramter in my query.
I wanted to make a 2nd path, so that I can call for the details of one object.
However its not working as expected.
Code in route2:
router.get('/', async (req, res) => {
console.log(req.params);
})
My parameters are always empty in this path. (I already checked that it can get called)
Wherever you use router add this to the top of that file:
i.e. in router.js
const router = require('express').Router({mergeParams: true});
notice the {mergeParams: true} you need this since you're nesting your routes in another file. If you left your routes all in on file, i.e.
app.use('/route/:id/details', (req, res) => {
console.log(req.params);// works fine
});
then you wouldn't need the mergeParams true flag.

Specifying a specific route in an Express Router used with an array of routes

The Express docs are clear about the fact that you can supply app.use with an array of routes for a particular piece of middleware.
They also describe how to split routers into separate files here.
But I can't see how to combine these two approaches.
index.js
const authRoutes = require('./routes/auth');
app.use(['/api/register', '/api/login'], authRoutes);
./routes/auth
router.route('/')
.all((req, res) => res.send('responds to both routes'); // <- this works
router.route('/register') // <- But how can I specify a specific route?
.all((req, res) => {
res.send('The register route');
});
It seems like you are trying to do something like this
const authRoutes = require('./routes/auth');
app.use('/api', authRoutes);
router.route(['/register', '/login']) . // respond to both
.all((req, res) => res.send('responds to both routes');
router.route('/register') // this is /api/register
.all((req, res) => {
res.send('The register route');
});
router.route('/login') // this is /api/login
.all((req, res) => {
res.send('The login route');
});
However there is something wrong with this logic , because your single routes /register and /login in auth file will never be called when you pass /api/login or /api/register they will go through the first array route. If you put the first route to the bottom then the array route respond to both route will be never called since it either goes to first /register route or 2nd /login route.

Including seperate route files in node.js

I am developing an application and I have defined my custom routes in a different way. I am using Web Storm IDE to develop and it has a specific folder of routes where all the routes are kept individually. I have the following code in my directory /routes/about.js file:
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('about', { title: 'About Us' });
});
module.exports = router;
Now in the app.js I have written the following code to include these route and use it:
var index = require('./routes/index');
var users = require('./routes/users');
var about = require('./routes/about');
app.use('/', index);
app.use('/users', users);
app.use('/about', about);
But when I click on about link, it does not open the page. Though, if I write the route in the app.js file directly as:
app.get('/about', function (req, res) {
res.render('about');
});
then it renders the page. Also, if I do not make separate routes and use the default routes file (/routes/index.js) and include this in that file, then also the code works fine. Can anyone explain or tell is there any mapping of these route files done which is missed by me, or I am doing something syntactically wrong
You probably created a route for /about/about. To fix, change the about router from this:
router.get('/about', ...);
to this:
router.get('/', ...);
This, then goes with:
app.use('/about', router);
which already includes the /about path. Everything in that router will already have /about at the beginning of the path.
Use below code in about file
app.get('/', function (req, res) {
res.render('about');
});
You have already defined '/about' route in main file so if you want to render page on '/about' so you need to define route like this '/' in about page.
For example route '/about/us' then function will be in about page :
app.get('/us', function (req, res) {
res.render('about us');
});
The method to redirect the route is correct, but you have not pass the route to app.
so you just need to do is ,
router.use('/about', about);
app.use('/', router);
Like wise add router in app

react router and express GET conflict

I'm not able to figure out how react router and express route working together.
I have this
app.get('*', function(req, res) {
res.sendFile(path.resolve(__dirname) + '/server/static/index.html');
});
// routes
const apiRoutes = require('./server/routes/api');
app.use('/api', apiRoutes);
The problem is my api can't use GET because it will redirect to index.html. If I remove the wildcard route, then react-router would not be able to work properly.
Your app.get('*') statement will match any request coming in. You can fix your problem by changing the order of the statements:
// routes
const apiRoutes = require('./server/routes/api');
app.use('/api', apiRoutes);
app.get('*', function(req, res) {
res.sendFile(path.resolve(__dirname) + '/server/static/index.html');
});
This way, any requests whose path's start with /api will be handled by your apiRoutes router, all the others are handled by the asterisk.

Express appears to be ignoring controller for root route

I am attempting to send all GET requests on my site (other than API requests) to a controller which checks for the presence of a signed-in user before showing the page. Otherwise, if not currently signed in, the user is sent to the sign-in page.
The below structure works perfectly for everything but the root route ('/'). For example, if I try to hit /admin or /games as a non signed-in user I am properly sent to the sign-in page. Likewise, if I am signed in each page shows properly (note: I am using AngularJS client-side). The one issue I have is that when I hit my root route the app attempts to show index.html without ever checking if the user is signed in. I'm confused as to why that route is handled differently, and why my pagesController is seemingly never invoked for this route. I've done some 'console logging' and confirmed that pagesController.index is called for each non-API route but '/'.
routes.js
'use strict';
var controllers = require('./controllers');
var v1Router = require('./routes/api/v1');
var pagesController = controllers.pagesController;
module.exports = function(app) {
app.use('/api', v1Router);
app.get('/logout', function(req, res) {
req.logout();
res.redirect('/');
});
app.get(['*'],
pagesController.index
);
};
pages.js
'use strict';
var path = require('path');
var index = function(req, res) {
if (req.user) {
res.sendFile(path.join(__dirname, '../assets', 'index.html'));
} else {
res.sendFile(path.join(__dirname, '../assets', 'signin.html'));
}
};
module.exports = {
index: index
};
Update: I changed my root from / to /a in my client-side routing and everything works perfectly. For whatever reason / is not being run through pagesController.index.
Update 2: So this line in my app.js is causing the issue:
app.use(express.static(path.join(__dirname, 'assets')));
With that line removed pagesController.index is properly called on /, however none of my static assets are served so simply removing that line does not solve it. How can I serve my static assets properly while ignoring index.html?
You can also handle the route in your conditional statements:
'use strict';
var path = require('path');
var index = function(req, res) {
if (req.user) {
res.sendFile(path.join(__dirname, '../assets', 'index.html'));
} if (req.url === '/') {
** Handle Case Here **
}
else {
res.sendFile(path.join(__dirname, '../assets', 'signin.html'));
}
};
module.exports = {
index: index
};
Ok, I did some research: A great article and possible solution here:(not sure if it fits your use case)
http://evanhahn.com/express-dot-static-deep-dive/
app.use(express.static(myStaticPath, {
index: ['jokes.txt', 'index.html']
})
You can simply give an array of files to serve as index, if the first is found it is served, if not, the second is served, and so on.

Categories

Resources