Express not catching request to '/' - node.js

I have a quite bizzare issue - somehow, Express does not capture my request to my root route.
My Route File looks to following:
'use strict';
var errors = require('./components/errors');
var auth = require('./controllers/auth');
var ensureLoggedIn = require('connect-ensure-login').ensureLoggedIn;
module.exports = function(app) {
// Insert routes below
// All undefined asset or api routes should return a 404
app.route('/:url(api|auth|components|app|bower_components|assets)/*')
.get(errors[404]);
app.route('/login')
.get(auth.login)
.post(auth.loginUser);
app.route('/logout')
.get(auth.logout);
// All other routes should redirect to the index.html
app.route('/*')
.get(ensureLoggedIn('/login'), function(req, res) {
console.log("req to /");
res.sendfile(app.get('appPath') + '/index.html');
});
};
So what happens:
I request '/' and it sends me directly to my root and the app runs. Except: It does not require me to login, and also the Log Output does not show that any request has been made.
If i request '/users' (Angular Route) it redirects me to '/login', as expected and then continues on its path.
Any idea what would be causing this behavior?

Are you exposing any static assets with express? If you are and you require your routes after you expose the assets, the request to "/" will just land in your public folder and do nothing.
Does this help? Could you post your server.js?
I ran into this issue earlier and it was driving me nuts.

It seems like it's related to the filename of the 'main' Page being served, before Angular takes over.
Originally, the file was names index.html which, as it seems like, prompted Node to serve it by default - Which is expected behavior, if no routes interfere.
After renaming the main file to application.html and changing the serve asset - all is well, problem solved.
I am still unsure though, why the Route would not fire and the index would overwrite it.

Related

Heroku Node/React Deployment Routes Everything to index.html

I have an app.js node main file where I define my api path as the following
app.get('/api/users', UserController.get);
Below in the same file I have the following
app.use(express.static(path.resolve(__dirname, "./front/build")));
app.get("*", function (request, response) {
response.sendFile(path.resolve(__dirname, "./front/build", "index.html"));
});
The index.html successfully serves React App.
If I open my heroku app somewhere at my-app.herokuapp.com it will open the React app which is intended but the Problem is my-app.herokuapp.com/api/users also serves index.html file instead of JSON that the endpoint is supposed to return.
I tried
I replaced endpoint route definition to come before the "" definition (didn't suffice)
EVEN more, I removed redirection to index.html but heroku still opens the index.html page with any type of request (the "" redirection still works). So, it might have cached something?
Is it about cache (how to clean?) or any other suggestions?
You should create routes and work in a proper flow for each functionality,
For Example:
//app.js
app.use("/api/user",userRoutes);
//UserRoutes
router.post("/signup",UserController.signup);
//UserController
exports.signup = async (req,res,next) => {
//Signup function to add a new user when the user provides required info
}
In this way, you code will be easily accessible and much efficient

node.js does not execute any code after serving the index.html file

I'm trying to assign a sessionId to the user when he visits the index.html page. However no code is executed after a GET request to "/" and index.html is sent as a response.
Following is the code in question
app.get('/', (req, res) => {
// A unique identifier for the given session
const sessionId = uuid.v4();
if(req.session.uuid)
{
} else {
req.session.uuid = sessionId;
}
console.log("Session ID : " + req.session.uuid);
res.sendFile(path.join(__dirname+'/public/index.html'));
})
Also is it good practice to explicitly send index.html file because it is sent even when the res.sendFile() call is removed.
My guess would be that you have an express.static() middleware handler before this that is serving the index.html so this code never gets to run.
express.static() will automatically send index.html if it sees a request for / and also sees an index.html file in the directory you've pointed express.static() at.
You have three options for fixing this:
You could move this handler before your express.static() middleware so it gets first crack at serving /.
You could move index.html to a different directory that express.static() is not looking at.
You can pass an option to express.static(path, {index: false}) to tell it not to serve index.html.

Express routing and URL parsing when using separate modules

I'd like to be able to parse a url query for data and use it in my response. In my app file I have the following:
var entry = require('./routes/entry');
app.use('/entry*', entry);
in my route file:
router.get('/:name', function(req, res) {
res.send(req.params.name);
});
module.exports = router;
Currently I am getting a 404 error.
I'm wondering how I can get a name parameter out of the url. So if someone were to type .../entry/example then the response would be "example."
A lot of my confusion stems from what should be handled by the router and what the app.use should have as its URL parameter. Thanks so much!
Remove the asterisk * from /entry and it should start working as expected. I created a local express application and inserting the asterisk causes the same issue.

Express - Setting different maxAge for certain files

I'm building a single page application using Express for the backend and AngularJS for the frontend and I'm having some cache problems.
I'm not using express views, only serving files with express.static middleware.
My static files are in public/app or public/dist depending on enviroment (dist has minified files).
app.use app.router
app.use express.static(cwd + '/public/' + publicFolder, maxAge: MAX_AGE)
When requesting '/', app.router verifies if user is logged in, and if everything is ok then index.html is served via express.static (I just call next() in the controller). If user is not logged in, it gets redirected to login.html
My problem is that if I set maxAge, my index.html file gets cached and the first request to '/' doesn't go through router. I can enter the app even if I'm not logged in.
If I set maxAge to 0, the problem goes away, but I want to cache all my *.js and *.css files.
What is the correct approach to this kind of problems? Start using views? Different express.static mount points?
You can always define individual routes without necessarily using views (although view templates aren't a bad idea). In this way you could define index.html just to apply the special case maxAge.
Just be sure to put the route before the static middleware.
If you wanted you could even use send, the same static server that the static middleware uses behind the scenes. Something like:
// install send from npm
var send = require("send");
app.get("/index.html", function (req, res) {
send(req, "/index.html")
.maxage(0)
.root(__dirname + "/public")
.pipe(res);
});
Or the more low level stream way, something like:
app.get("/index.html", function (req, res) {
res.setHeader('Content-Type', 'text/html');
res.setHeader('Cache-Control', 'public, max-age=0');
// Note that you'd probably want to stat the file for `content-length`
// as well. This is just an example.
var stream = fs.createReadStream(__dirname + '/public/index.html');
stream.pipe(res);
});

How to use AngularJS routes with Express (Node.js) when a new page is requested?

I'm using Express, which loads AngularJS from a static directory. Normally, I will request http://localhost/, in which Express serves me my index.html and all of the correct Angular files, etc. In my Angular app, I have these routes setup, which replace the content in an ng-view:
$routeProvider.when('/', {
templateUrl: '/partials/main.html',
controller: MainCtrl,
});
$routeProvider.when('/project/:projectId', {
templateUrl: '/partials/project.html',
controller: ProjectCtrl,
});
$locationProvider.html5Mode(true);
On my main page, I have a link to <a href="/project/{{project.id}}">, which will successfully load the template and direct me to http://localhost/project/3 or whatever ID I have specified. The problem is when I try to direct my browser to http://localhost/project/3 or refresh the page, the request is going to the Express/Node server, which returns Cannot GET /project/3.
How do I setup my Express routes to accommodate for this? I'm guessing it will require the use of $location in Angular (although I'd prefer to avoid the ugly ?searches and #hashes they use), but I'm clueless about how to go about setting up the Express routes to handle this.
Thanks.
with express 4, you probably want to catch all requests and redirect to angularjs index.html page.
app.use(app.router); doesn't exist anymore and res.sendfile is deprecated, use res.sendFilewith an uppercase F.
app.post('/projects/', projectController.createProject);
app.get('/projects/:id', projectController.getProject);
app.get('*', function (req, res) {
res.sendFile('/public/index.html');
});
put all your API routes before the route for every path app.get('*', function (req, res){...})
I would create a catch-all handler that runs after your regular routes that sends the necessary data.
app = express();
// your normal configuration like `app.use(express.bodyParser());` here
// ...
app.use(app.router);
app.use(function(req, res) {
// Use res.sendfile, as it streams instead of reading the file into memory.
res.sendfile(__dirname + '/public/index.html');
});
app.router is the middleware that runs all of your Express routes (like app.get and app.post); normally, Express puts this at the very end of the middleware chain automatically, but you can also add it to the chain explicitly, like we did here.
Then, if the URL isn't handled by app.router, the last middleware will send the Angular HTML view down to the client. This will happen for any URL that isn't handled by the other middleware, so your Angular app will have to handle invalid routes correctly.
I guess I should have clarified that I wasn't interested in using a template engine, but having Angular pull all of the HTML partials on it's own, Node is functioning completely as a static server here (but it won't be for the JSON API. Brian Ford shows how to do it using Jade here: http://briantford.com/blog/angular-express.html
My app is a single-page app, so I created an Express route for each possible URL pattern, and each of them does the same thing.
fs.readFile(__dirname + '/public/index.html', 'utf8', function(err, content) {
res.send(content);
});
I was assuming I would have to pass some request variables to Angular, but it looks like Angular takes care of it automatically.

Resources