Override app.get('*', func) route in express - javascript

I have an Angular app running alongside a NodeJS server.
This code in my server.js file:
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'dist/index.html'));
});
require('./server/routes/routes')(app, passport);
Seems to be preventing any GET requests to my api, for example:
module.exports = function (app, passport) {
app.get('/api/profile', isLoggedIn, function (req, res) {
res.status(200).json(req.user);
});
When the exported /api/profile handler is changed to a post the request works.
Should the route not overwrite the initial handler? How to achieve this? Can I serve the app for all routes excluding beginning with '/api'?

Move the app.get('*') so it becomes the last route that gets declared:
require('./server/routes/routes')(app, passport);
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'dist/index.html'));
});
Express checks route handlers in order of their declaration, not in order of their specificity (how well they match a particular request).

Related

Node.js Express return 404 if file not found in only Assets folder

I am trying to create an SPA using Express with following code
var express = require('express');
const path = require('path');
var app = express();
app.use('/assets', express.static(path.resolve(__dirname, 'www', 'assets')));
app.get('/*', (req, res)=>{
res.sendFile(path.resolve('www', 'index.html'));
});
var server = app.listen(3000, function(){});
This code works good but the problem is this responds with my index.html even when a file is not found in my assets folder. I want it to respond with error of 404 Not Found if some url is not present in assets folder
I tried using this code after line app.use('/assets'...
app.use(function (req, res, next) {
res.status(404).send("404 Not Found");
});
but not working
Issue is with
app.get('/*', (req, res)=>{
res.sendFile(path.resolve('www', 'index.html'));
});
Instead, use
app.get('/', (req, res)=>{
res.sendFile(path.resolve('www', 'index.html'));
});
So, I finally got the way to solve it
app.get('/*', (req, res)=>{
if(req.path.includes('/assets'))
{
fs.access(req.path, (err) => {
if(err)
{
res.status(404).send("Sorry can't find that!");
return;
}
});
}
res.sendFile(path.resolve('www', 'index.html'));
});
In the code, I have told to check if the request is about a file located in assets folder then check if the file exists, if does not exists then send 404 error with message and just return, otherwise do nothing but return the file.

Refreshing the page using Node.js / Express?

I need to refresh the page in my small Node and Express app as soon as the user connects. I have tried res.redirect('index.html') in the second snippet, but it throws an error when I try to connect to the root URL.
The following code is run when the user connects to the root URL:
app.get('/', (req, res) => {
res.redirect('/index.html')
app.use(express.static(path.join(__dirname, 'public')))
});
and I detect when the user connects with:
io.on('connection', (socket) => {}
Thanks in advance!
app.get('/', (req, res) => {
// res.redirect('back');
// OR
res.redirect(req.get('referer'));
app.use(express.static(path.join(__dirname, 'public')))
});

why slash URL runs with all of other URLs in the middleware of NodeJS?

Why I enter http://localhost:3000/product on the browser, the output will be both outputs of '/' and '/product'?
Please look at this snippet code.
const express = require('express');
const app = express();
// http://localhost:3000/product
app.use('/product', (req, res, next)=>{
console.log('In product page');
res.send('<h1>Product Page</h1>');
});
// http://localhost:3000/
app.use('/', (req, res, next)=>{
console.log('In main page');
res.send('<h1>Main Page</h1>');
});
app.listen(3000);
This image is my app's output.
It could have multiple reasons. One that I think of right now is that the browser requests http://localhost:3000/favicon.ico automatically after product.html, which triggers the use('/', ...) route.
Maybe you should use app.all(...) instead of app.use(...), to avoid this "wildcard" on every path that should rather be a 404 page.
The app.use() method is used to bind application level middleware. Not for accepting GET request as you are expecting.
You should use
// http://localhost:3000/product
app.get('/product', (req, res)=>{
console.log('In product page');
res.send('<h1>Product Page</h1>');
});
// http://localhost:3000/
app.get('/', (req, res)=>{
console.log('In main page');
res.send('<h1>Main Page</h1>');
});
Because in express whatever you define with app.use() is middleware and it always executes until and unless it has some path defined
app.use('/', (req, res, next)=>{
console.log('In main page');
res.send('<h1>Main Page</h1>');
});
above will always execute because it contains root path and every url has root path
Check this link for further info https://expressjs.com/en/4x/api.html#app.use
You should define your routing with express router using app.get("/") or app.post("/") and it will help for more info https://expressjs.com/en/guide/routing.html

One router is not triggered when declaring routers in different files

I would like to breakdown my routes in several files, typically something for the client routes and something for the api.
So I declare my app, then
app.use('/', clientRoutes);
app.use('/api', apiRoutes);
In clientRoutes:
module.exports = function (webapp_client_path){
router.get('/', function (req, res) {
res.sendFile(path.join(webapp_client_path, '/','index.html'));
});
return router;
};
In apiRoutes:
module.exports = function(passport){
router.post('/signup', function(req, res) {
console.log('signup!', req.body);
});
return router;
}
So the problem is that the apiRoutes is not triggered, if I put everything in the same cleintRoutes file it works. I've tried to change the root also ( app.use('/', apiRoutes); and inside the file router.post('/api/signup'...) but it didn't change anything.
I'm pretty sure I'm missing something basic here but can't find what it is yet. Thanks for your help !
I found the problem.
You need to execute the router then pass it as a middleware.
var apiRoutes = require('./routes/apiRoutes')();
app.use('/', apiRoutes);

I can't successfully chain my route handlers?

I've got a node.js/express app I'm working on and routes that look like-
app.post('/user/:who/update', isLoggedIn, userUpdate.save);
inside userUpdate.save I'm calling res.redirect or res.render (different routes but same idea). I don't like this. I'd like to keep my res.* calls in routes.js, but when I attempt this
app.post('/user/:who/update', isLoggedIn, userUpdate.save, function(req, res) {
res.redirect('/user/'+req.user.local.username);
});
with a call to next(req, res) at the end of userUpdate.save, the res.redirect function isn't called. What I think next() is, does not seem to be what it actually is. What am I missing?
The call to next() bypasses the remainder of your callbacks.
See this ref http://expressjs.com/api.html#app.post.method
Take a look at this example and alternately comment out each of the next() calls (and then both of them) and watch where the execution flows.
var express = require('express');
var app = express();
app.get('/test', function(req, res, next){
console.log('/test callback1');
next('route');
//next();
}, function(res, res, next){
console.log('/test callback2');
res.send('sent from /test/cb2')
});
app.get('/test', function(req, res){
console.log('response from /test route handler 2');
res.send('sent from /test route handler 2');
})
var server = app.listen(8911, function (s) {
console.log('Listening on port ', server.address().port);
});

Categories