How to remove the preference for index.html in nodejs? - node.js

In my public folder I have the index.html file and my route handler is like this
router.get('/', function (req, res, next) {
// res.send('index.html');
if (req.user)
res.redirect('home');
else
res.redirect('login');
});
As you can see , I have commented out the serving of index.html file , but nodejs still serves the index.html from the public directory instead of redirecting to home or login. But if I remove/rename the index.html file then it works fine.
So How can I configure nodejs so that it invokes the route handler , not the serve index file on request ?

The express.static() middleware includes an index option that allows you to change the default file name.
Or, for your intentions, to disable the feature entirely:
app.use(express.static(path.join(__dirname, 'public'), {
index: false
}));

This is due to ordering of the app.use , previously it was
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', index);
changing this to
app.use('/', index);
app.use(express.static(path.join(__dirname, 'public')));
Solves the problem.

Related

React App giving 404 on main js and css

I built a react app using "react-scripts". The application runs perfectly on my local development server but when I deploy to my actual server the applications seems to not find the main JS and CSS files being compiled. I get 404 on both.
Following is the information that might help.
The files on the server are located at
ads/build/static/js and ads/build/static/css || respectively
The 404s I am getting are on the following files:
https://www.example.com/ads/build/static/css/main.41938fe2.css
https://www.example.com/ads/build/static/js/main.74995495.js
Here is how my server is configured:
const express = require('express');
const path = require('path');
const app = express();
const favicon = require('serve-favicon');
//favicon
app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.get('/ads', function (req, res) {
app.use(express.static(path.join(__dirname, 'build/static')));
console.log(path.join(__dirname, 'build'));
res.sendFile(path.join(__dirname, '/build/index.html'));
});
app.listen(9000);
In my package.json I have also included the homepage parameter as:
"homepage" : "https://www.example.com/ads
UPDATE
When I run the app on the server itself with the following path:
dedicated-server-host:9000/static/js/main.74995495.js that renders the JS file correctly
Is there some configuration that I am missing, the routing doesn't seem to be working. Please advise.
Use some indentation so you will see error like this:
app.get('/ads', function (req, res) {
app.use(express.static(path.join(__dirname, 'build/static')));
console.log(path.join(__dirname, 'build'));
res.sendFile(path.join(__dirname, '/build/index.html'));
});
You are setting the static route inside of the /ads handler, will add a new express.static route handler on every GET /ads request.
This will set the static route on server startup:
app.use(express.static(path.join(__dirname, 'build/static')));
app.get('/ads', function (req, res) {
console.log(path.join(__dirname, 'build'));
res.sendFile(path.join(__dirname, '/build/index.html'));
});
or:
app.get('/ads', function (req, res) {
console.log(path.join(__dirname, 'build'));
res.sendFile(path.join(__dirname, '/build/index.html'));
});
app.use(express.static(path.join(__dirname, 'build/static')));
But make sure that you get the path right - for example you may need:
app.use('/ads/build/static', express.static(path.join(__dirname, 'build/static')));
if you want the URL in your question to work.
To make it much simpler, you could use just this single handler to make express.static handle both the css/js and index.html at the same time:
app.use('/ads', express.static(path.join(__dirname, 'build')));
and change your index.html to use:
https://www.example.com/ads/static/css/main.41938fe2.css
https://www.example.com/ads/static/js/main.74995495.js
instead of:
https://www.example.com/ads/build/static/css/main.41938fe2.css
https://www.example.com/ads/build/static/js/main.74995495.js
Sometimes getting your paths structure right in the first place can make your route handlers much easier.

Express static serves index.html How to deny it?

When I serve my angular 5 app from node express I face this issue as express static serves index.html when I visit domain.com but I when I visit domain.com/something it works correctly can some help how do I solve this
app.use(express.static(path.join(__dirname, 'dist'))); //This line serves index.html how to deny it
app.use("/api", routes);
app.get('*', function(req, res) { //The reason it needs to be * so that it works with angular routes or it wont work
//This is never called when i visit domain.com. but it does when i visit domain.com/somthing
console.log("i was serverd");
res.sendFile(path.join(__dirname, 'dist/index.html'));
});
Thanks in advance :)
Found a solution
var options = {
index: false
}
app.use(express.static(path.join(__dirname, 'dist'), options));
index : Sends the specified directory index file. Set to false to disable directory indexing.
Refer: http://expressjs.com/en/api.html
I have found a workaround for your prooblem
app.use('/',(req,res,next)=>{
if(req.path!='/')
next();
console.log('ii');
res.sendFile(path.join(__dirname,'dist/index.html'));
},express.static(path.join(__dirname, 'dist')));
app.get('*',(req,res,next)=>{
console.log('ii');
res.sendFile(path.join(__dirname,'dist/index.html'));
});
This will cover for all your requests. But in this way you would have to write same code in 2 routes
Replace * with /.
This should be registered before the app.use(express.static call. (Thank you jfriend00)
Ex :
app.get('/', function(req, res) { //see, no asterix
//This is never called when i visit domain.com. but it does when i visit domain.com/somthing
console.log("i was serverd");
res.sendFile(path.join(__dirname, 'dist/index.html'));
});
app.use(express.static(path.join(__dirname, 'dist')));

Node.js + Express: What do I have to serve the specific folder's path to express.static?

I wrote the following code:
var express = require('express');
var app = express();
app.use('/', express.static(__dirname ));
app.get('/', function (req, res) {
res.sendFile('./dist/index.html');
});
app.listen(3000, function() {
console.log("Listening on port 3000");
});
which doesn't work. When open the browser and go to "localhost:3000" I get the error:
path must be absolute or specify root to res.sendFile
Of course the once I fix the line that starts with "app.use..." to:
app.use('/', express.static(__dirname + "./dist"));
then everything works right.
Can you please explain why? What's wrong with giving "express.static" a path of a parent folder of the direct folder of the file sent?
Try changing the order. Instead of:
app.use('/', express.static(__dirname ));
app.get('/', function (req, res) {
res.sendFile('./dist/index.html');
});
Try:
app.get('/', function (req, res) {
res.sendFile(path.join(__dirname, './dist/index.html'));
});
app.use('/', express.static(__dirname));
// OR:
app.use('/', express.static(path.join(__dirname, 'dist')));
Plus use path.join() to join paths. You need to require path first:
var path = require('path');
See this answer for more info on serving static files and why path.join is important:
How to serve an image using nodejs
Now, your problem was not about express.static but about res.sendFile. When you changed express.static path to a different one, then the file you previously wanted to send with res.sendFile was probably found by express.static and the handler with res.sendFile was not run at all. Before the change, the express.static wasn't finding the index.html file and was passing the request to the next handler - which had a bad res.sendFile invocation. That's why it appeared to solve the problem with the error, because the code causing the error was no longer called.

Node.js catch-all route with redirect always renders index page with Angular regardless of url

Essentially when I use a catch-all route and use res.redirect('/') regardless of the url I enter it will always render the index/home page (ie Angular does not seem to 'see' the full url) however if I place res.render('index') in the catch-all route everything works fine. I don't want repeat code and redirecting to '/' should work, I have probably made a stupid mistake somewhere here and any help would be much appreciated!
Angular routing:
app.config(function ($routeProvider, $locationProvider) {
$locationProvider.html5Mode(true);
$routeProvider
.when('/',
{
templateUrl: 'partials/home.jade'
})
.when('/about',
{
templateUrl: 'partials/about.jade'
})
.otherwise( {redirectTo: '/'});
});
This will correctly render the about page when entering site-address/about:
app.get('/', function (req, res) {
res.render('index');
});
app.get('/partials/:name', function (req, res) {
res.render('partials/' + req.params.name);
});
app.get('*', function (req, res) {
res.render('index');
});
This will always just show the index page:
app.get('/', function (req, res) {
res.render('index');
});
app.get('/partials/:name', function (req, res) {
res.render('partials/' + req.params.name);
});
app.get('*', function (req, res) {
res.redirect('/');
});
Configuration if it helps:
// Configuration
app.configure(function () {
app.set('port', process.env.PORT || 1337);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.static(path.join(__dirname, 'public')));
app.use(app.router);
});
This is by design.
When you use res.redirect('/'), Node/Express is sending an HTTP redirect, which will change the URL in the browser, thus when your index template is rendered, and when the angular code is run, the URL is /, regardless of what the user entered (the whole point of the redirect).
When you omit the redirect and just send the template as a response, NodeJs responds with an HTTP 200 (success) along with HTML content. Since the URL didn't change, when your application runs, the angular routing properly routes.
EDIT TO ADD: Address Comment
Rather than have two routes render the same template, I would get rid of the / route all together, and just have the catch-all render the index template, which will then turn control over to the Angular router.
Otherwise, I would consider splitting your routes conceptually: All your application routes are specifically sent to angular router, and you render static routes via nodejs, and use your catch all to render a more appropriate page for a missing or unknown resource (more helpful for your users).
You can use regex-like languages to specify a single handler:
app.get('/()|(about)|(contact)/',function(req,res) {/* handle */});
For folder structure:
root
-web.js
-dist/index.html
-dist/rest of the page
Just paste the following snippet to your web.js
nodeApp.use('/', express.static(__dirname + '/dist'));
nodeApp.get('/[^\.]+$', function(req, res){
res.set('Content-Type', 'text/html')
.sendfile(__dirname + '/dist/index.html');
});
I have a problem where when I use the catch-all routing, all of my static assets (stylesheets, javascript files etc) don't load:
app.use(app.router);
app.use(express.static(path.join(__dirname, frontend.app)));
// when this is removed, I can load static assets just fine
app.get('*', function(req, res){
res.render('main');
});
When the app.get('*', ...) part is removed, I can load the static assets just fine (i.e. I can type in 'examplejavascript.js' and see the javascript file. When it is there however, express catches the assets.
$locationProvider.html5Mode(true);
are you sure your requests are hitting the nodejs server. using this means, angularjs will try to search for urlmapping inside browser.
try by commenting
$locationProvider.html5Mode(true);

Detect IE in expressjs, but can't get static files

I've tried to detect IE by using expressjs, the code surely redirect me to the error page.
But the problem is that it won't render css files and get image files in my folder.
I think the problem is that expressjs redirect to error_page before the static path is set.
So I put app.all('*', ieRedirecter);, after
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.static(__dirname + '/uploads'));
The problem is still occur... could someone help me out, thanks!
My settings
function ieRedirecter(req, res, next) {
if(req.headers['user-agent'].indexOf("MSIE") >= 0) {
var myNav = req.headers['user-agent'];
var IEbrowser = parseInt(myNav.split('MSIE')[1])
if(IEbrowser < 9) {
res.render('error/browser_error', {title : 'not supporting your browser'})
} else {
next();
}
} else {
next();
}
};
app.configure(function(){
app.set('port', process.env.PORT || 3000);
...
...
...
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.static(__dirname + '/uploads'));
app.all('*', ieRedirecter);
})
This order doesn't work:
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.static(__dirname + '/uploads'));
app.all('*', ieRedirecter);
app.router is the middleware that handles all your routing requests, including app.all(), even though you declare that route after your other middleware (fun fact: at any moment you declare a route – using app.{get,post,all,...} – the app.router middleware is inserted into the middleware chain automatically).
If possible, the easiest solution would be to move the static and IE middleware to before your routes (but I realize that might cause problems with your application setup):
// static middleware first...
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.static(__dirname + '/uploads'))
// ...followed by the IE check
app.use(ieRedirecter);
// ...followed by your routes
app.get('/', ...);
...
Another solution would be filter out requests for static resources in your ieRedirecter middleware by looking at req.path, but that assumes that you can easily identify those requests (like if they start with /css or /js).

Resources