Angular - Node - Possible to tell node which block from routes request from - angularjs

Is it possible to tell a request to my Node App req in:
app.get('/*', function(req, res) {
res.sendFile(__dirname + '/site/index.html')
});
From which block of my Angular routes it is from (i.e. I want to be able to identify whats from the otherwise block);
.when('/user',
{...}
)
.when('/login',
{...}
)
.otherwise(
{...}
)
The reason I want it because I want to do something like:
app.get('/*', function(req, res) {
if (req is from otherwise block) {
res.status(400).sendFile(__dirname + '/site/index.html')
} else {
res.sendFile(__dirname + '/site/index.html')
}
});
The only thing i can otherwise think of is to create an array of all the allowed routes but I don't like duplication :p

Since the only link between Angular and Node is the HTTP request it's making, all you can do is retrieve the url and analyze which route it came from.
I'd define the routes you know about in Node, and then have a fallback for 404 errors:
app.get(['/login', '/user'], function(req, res) {
res.sendFile(__dirname + '/site/index.html')
});
app.get('*', function(req, res) {
res.status(404).sendFile(__dirname + '/site/404.html')
});

Related

Express - enabling catch all for Angular 1.x html5Mode with multiple router files is not working

Okay so this question originates from this post, which is also my question but sorta moved onto this problem.
Now the problem is, my angular app works but when it comes to Node routes, like /login, the browser thinks it's an Angular route. The browser does detect it as a Node route when I refresh the whole page but not when I am navigating the site once Angular routing has kicked in.
Long story short, here are my route files:
require('./routes/routes.js')(express, app);
require('./routes/default.js')(express, app);
routes.js file:
module.exports = function(express, app){
var router = express.Router();
router.get('/', function(req, res){
res.render('index');
});
router.get('/login', function(req, res){
if (req.isAuthenticated()){
res.render('index');
} else {
res.render('login');
}
});
default.js:
module.exports = function(express, app, passport, Promise){
var defaultRouter = express.Router();
defaultRouter.get('/*', function(req, res, next) {
res.render('./views/index.html');
});
};
Your help will be very much appreciated.
Thanks
I gave up on making this work on the root URL so I added /index to the baseURL like this:
index.html file:
<head>
<base href="/index/">
</head>
The, I added a catch all to the routes.js file, as below:
module.exports = function(express, app){
var router = express.Router();
router.get('*', function(req, res, next) {
if(req.url == '/' || req.url == '/login'){
next();
} else {
res.sendfile('./views/index.html');
}
});
router.get('/', function(req, res){
res.render('index');
});
router.get('/login', function(req, res){
if (req.isAuthenticated()){
res.render('index');
} else {
res.render('login');
}
});
With the angular file of course having this:
$locationProvider.html5Mode({
enabled: true,
requireBase: true
}).hashPrefix('');
And there. It works like a charm now.
I hope this helps whoever are in my shoes.

Express serving index.html from Angular html5 mode not working

I'm trying to use html5 mode in Angular JS app for sake of SEO. However, I faced the problem for Express serving index.html to request. The deep linking didn't work and cannot refresh page.
App.js
app.use(serveStatic(path.join(__dirname, 'public')));
app.use(serveStatic(path.join(__dirname, 'node_modules')));
app.use(serveStatic(path.join(__dirname, 'app_client')));
app.use('/api', routesApi);
app.all('/*', function(req, res, next) {
res.sendFile('./app_client/index.html', { root: __dirname });
console.log("send index");
});
I already try many researches from many sources, approach such as
app.get('/', function(req, res) {
res.sendFile('index.html');
});
or
router.get('/', function(req, res) {
res.sendFile(path.join(__dirname, 'app_client', 'index.html'));
});
or
app.get('/*', function(req, res) {
res.sendFile(__dirname + '/index.html')
});
None seems to work. I know that something must be wrong in my code, but i don't know where.
Found answer at lasts
app.get('/*', function(req, res, next) {
res.sendFile(__dirname + '/app_client/index.html');
}

node express routing params not catching

I have this
router.put('/user:resourceId', function(req, res) {
User.findOneAndUpdate({resourceId: req.params.resourceId}, req.body, function(err, user) {
if (err)
res.send(err);
res.send(user);
});
});
and in my angular code I have
updateResource: function(resource){
var self = this;
return $http.put('api/resources/resource', resource, {params:{resourceId:resource.resourceId}}).then(function(response){
return response.data;
}, function(err){
$log.error('Error updating', err);
});
}
Why isn't this path catching? It works when I remove the params.
Your route looks a little off, try the following:
router.put('/user/:resourceId', function(req, res) {
...
});
For a URL that looks like: /user/123, where req.param.resourceId is 123.
It looks like your angular code is pointing to /api/resources/resource though, so I can understand why it's perhaps not matching your Express route for /user/:resourceId - (Unless your Express router is set to handle request for something like the following: /api/resources/resource/user/:resourceid?

NodeJs + ExpressJs app routing odd behavior

I am learning ExpressJS. So far I have setup a simple todo app with user authentication using PassportJS. I use Mongoose for repository. There is nothing in the web to explain the odd behavior that I'm seeing with my route setup.
Scenario:
When I hit get /passport it will direct to the passport page
(login/signup)
When I hit get /aslkdjf it will direct to the passport page if
user is not logged in, else it will direct to the file
/public/index.html)
When I hit get / it should direct to the passport page if user
is not logged in, but it goes to /public/index.html instead and
my todo app would fail as req.user.username under /api/todos is
undefiend
Strangely, when I remove the router.get('/*', ... configuration, my app would still go to public/index.html, when I hit base path '/', but not when I hit '/asdfa'.
...
function loggedIn(req, res, next) {
if (req.user) {
next();
} else {
res.redirect('/passport');
}
}
var router = express.Router();
// passport ----------------------------------------------------------------
// get passport page
router.get('/passport', notLoggedIn, function(req, res) {
res.sendfile('./public/passport.html');
});
// post login
router.post('/login', passport.authenticate('login', {
successRedirect: '/',
failureRedirect: '/passport',
failureFlash: true
}));
// post registration
router.post('/signup', passport.authenticate('signup', {
successRedirect: '/',
failureRedirect: '/passport',
failureFlash: true
}));
router.get('/logout', function(req, res) {
req.session.destroy();
req.logout();
res.redirect('/');
});
// api ---------------------------------------------------------------------
// get all todos
router.get('/api/todos', function(req, res) {
// use mongoose to get all todos in the database
Todo.find({owner: req.user.username}, function(err, todos) {
// if there is an error retrieving, send the error. nothing after res.send(err) will execute
if (err)
res.send(err)
res.json(todos); // return all todos in JSON format
});
});
// create todo and send back all todos after creation
router.post('/api/todos', function(req, res) {
// create a todo, information comes from AJAX request from Angular
Todo.create({
owner: req.user.username,
text : req.body.text,
done : false
}, function(err, todo) {
if (err)
res.send(err);
// get and return all the todos after you create another
Todo.find({owner: req.user.username}, function(err, todos) {
if (err)
res.send(err)
res.json(todos);
});
});
});
// delete a todo
router.delete('/api/todos/:todo_id', function(req, res) {
Todo.remove({
_id : req.params.todo_id
}, function(err, todo) {
if (err)
res.send(err);
// get and return all the todos after you create another
Todo.find({owner: req.user.username}, function(err, todos) {
if (err)
res.send(err)
res.json(todos);
});
});
});
// application -------------------------------------------------------------
router.all('*', loggedIn);
router.get('/*', function(req, res) {
res.sendfile('./public/index.html'); // load the single view file (angular will handle the page changes on the front-end)
});
app.use('/', router);
app.listen(3000);
console.log("App listening on port 3000");
Can someone explain to me what is going on? All I want to achieve is to make the app re-route user to the login page when they are not logged in and they go to www.myapp.com/
So apparently the problem is that HTML defaults to finding an index.html file in any folder within the root. When I change the html file to something else like abc.html the problem is solved. Seems like a bug to me.

Changing static content directory

I am trying to set the express.static path to something different based on a session variable. The relevant code is below.
app.use( '/', function(req, res, next ) {
if ( req.session.loggedIn ) {
console.log("loggedIn : " + req.session.loggedIn);
app.use('/', express.static(__dirname + '/private'));
next();
}
else {
console.log("not logged in.");
app.use('/', express.static(__dirname + '/public'));
next();
}
});
When I start the application, I begin with not having req.session.loggedIn set. So it will use the static content in the /public directory (which contains an angular powered application for public users.) I then do a login (code below)
app.post('/login', function( req, res ) {
req.session.loggedIn = true;
var message = {};
message.success = true;
message.text = "Logging you in...";
res.json(message);
});
Which sets the req.session.loggedIn variable to be true. I then hit refresh on the page (and have tried hard refresh, and cache clear/refresh as well). The console.log tells me "loggedIn : true" as expected, however it does NOT load the static content from the /private directory. It instead continues to load from the /public directory.
Can anyone shed light on this issue?
The express.static is just another middleware so you can call it directly with the request and response parameters. Instead of adding it to the '/' route directly you could wrap it in another middleware like this:
var public_pages = express.static(__dirname + '/public');
var private_pages = express.static(__dirname + '/private');
app.use('/', function(req, res, next) {
if(req.session.loggedIn == 1) {
private_pages(req, res, next);
} else {
public_pages(req, res, next);
}
});

Resources