Express App Serving Unwanted Static Files - node.js

I have a react app that is served by express. The entire app is included in public/index.html.
Right now my server.js looks like this:
1 const express = require('express');
2 const path = require('path');
3 const port = process.env.PORT || 8080;
4 const app = express();
5
6 // the __dirname is the current directory from where the script is running
7 app.use(express.static(__dirname));
8
9 app.get('*', (req, res) => {
10 res.sendFile(path.resolve(__dirname, 'public/index.html'));
11 });
12
13 app.listen(port);
However, somehow, files like package.json and /.ssh/known_hosts are being served, things that obviously shouldn't be avaialible.
I'm not sure why app.get('*', (req, res)... isn't catching all requests, and why app.use(express.static(__dirname)); seems to be the only configuration that allows my app to server ANY static files.
I haven't had any luck with app.use(express.static(__dirname+'/public')); or
app.use( '/', express.static(__dirname + '/public'));
or anything else I can find.
EDIT---
My project directory looks like:
/myproject
package.json
server.js
/public
index.html
I want ALL requests to simply serve index.html
What I'm still not understanding is why
app.use('*', express.static(path.resolve(__dirname,'/public/index.html')));
does not serve anything.
Also, why in the above example, res.sendFile() does nothing without first having called express.static(). If I delete line 7, then nothing is served.

So, never ever do this:
app.use(express.static(__dirname));
in your main server directory. That exposes ALL your server files to be viewed.
When using express.static() to serve a whole directory, you should create a directory that contains ONLY files intended for public consumption and then point express.static() at that.
I'm not sure why app.get('*', (req, res)... isn't catching all requests
Because that app.get('*', ...) is AFTER your express.static() so if the express.static() finds a matching file, the app.get('*', ...) never even sees the request. It's already handled and routing doesn't continue any more.
As always with express.static() to advise on exactly what you should do, we need to know the precise configuration you have. Where are the public files in your file system relative to your main server directory and what URLs are you intending to use in the client to refer to those publicly available files.
Here's a theoretical example (since you haven't provided your specifics):
Let's suppose you have files like this:
/myproject
app.js
/public
main.css
And, suppose you want to be able to use /main.css as the URL from the client. For that, you would just do this from within app.js:
app.use(express.static(path.join(__dirname, "public")));
In this first example, where you're serving these static files at the top level path, then you have to make sure there are no naming conflicts between these top level resources and any actual routes you want to serve.
If you wanted the client-side URLs to be /assets/main.css, then you would do this:
app.use("/assets", express.static(path.join(__dirname, "public")));
In this example, you must make sure that the /public sub-directory (and any sub-directories it might have) contains only files intended to be publicly accessible.
Adding a path to the public URL such as /assets removes the chance of a naming conflict between your static assets and your top level routes. This can be a good thing because in any multi-person project, it's not uncommon that the person working on the static assets (like CSS files) is different than the person working on server routes so the two main not be directly aware of what names each other is using. In a single person project, you would certainly just keep it all in your head and avoid accidental naming conflicts that way.
FYI, my preference for folder organization is more like this:
/myproject
/server
app.js
/public
main.css
Where it's 100% obvious which are server files and which are public files. Then, to serve the public files from within app.js with a URL of /assets/main.css, I'd do this:
app.use("/assets", express.static(path.join(__dirname, "../public")));
From your comments:
I just want to serve public/index.html for all ('*') GET requests. All other data comes from separate apis. it seems that res.sendFile() doesn't work without first using express.static. The above code resides in server.js
If all you want to do is to serve public/index.html for all requests (where public is a sub-directory below where app.js is located), then remove the express.static() middleware entirely.
Just use this from app.js:
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'public/index.html'));
});

remove app.use(express.static(__dirname));
as that tells express to load all files that exist

app.use(express.static(__dirname)); will make your app insecure.
Always print out the URLs in the console like path.resolve(__dirname, 'public/index.html') to find out if there is something wrong in it. Seems aiming to the root directory for static files makes problem. Put them in the conventional public directory then try it out again

Related

Node Express force all static routes to point to root path

I have a node.js application that I am trying to genericize so that no matter the URL on the back end it always uses the root path to serve static files.
So currently my app sits at https://myapp.heroku.com
I have some js, css, images and a few other static files.
What I want is when the url looks like https://myapp.heroku.com/brand/somebrand that the files that are served are served form the root as well including any internal references inside said files.
I have ensured that all paths begin with a '/' and have also tried the following in every combination possible.
app.use('/', express.static(__dirname + '/public', options));
app.use('*', express.static(__dirname + '/public', options));
app.use(express.static(path.join(__dirname, 'public')));
am I on the right track?
This app is actually being loaded by another system which may actually be the problem, unfortunately I cannot debug on that system so I need to rule this out first.

Use non-absolute Paths with node.js and express

i'm having issues running my node server on localhost.
right now it only allows me to run it with a static path:
app.get("/", function(req, res){
res.sendFile("/Users/name/Documents/_privat/dungeon/index.html");
});
of course that's not where i wanna go.
i tried many ways to embedd the dynamic path, this is my file-structure:
*dungeonapp
- main.html
- js
--client
---main.js (and others)
--server
---server.js
- style
--style.css
So if I run everything static my application runs on localhost, but it also won't load my css files neither the js files.
Where am i going wrong? all the regular path embedding didn't work like "/../index.html"
Express response sendFile() method has a second options argument where you can express your root path for path resolution. See docs for more information. You can use {root: __dirname} as second argument to sendFile() and file paths will be resolved relative to the javascript file that calls sendFile(). In your case with the directory structure indicated in your question the code on server.js would be:
app.get("/", function(req, res){
res.sendFile("../../main.html", {root: __dirname});
});
This way you can move your project to any folder and sendFile() will continue to work. I think you should reword your question because you are talking about absolute paths and not static paths.
Normally you would do something like have two subfolders in the root of your project, one for server code and one for client (i.e. web) code and then you can use app.use(express.static('<filepath>')) in your server code to serve the static client files.
As an example, in my project root I have 2 folders, one called app and one called web. In the main app.js, I have app.use(express.static(__dirname + '/../web/')); which serves the static content. Normally this would be the first use of app.use() so that none of the other routes need to be checked before your content is served.

Express assets served through wildcard route

I've got a strange bug in my MEAN application whereby asset files are being served through my wildcard route.
I want to serve a single HTML file via express and let Angular take care of all the routing etc. That route is setup like so (defined after middleware):
app.get('*', function (req, res) {
res.sendfile('./app/www/index.html');
});
I'm using the express static middleware which is setup like this:
app.use(express.static(__dirname + './app/www'));
My project structure (simplified):
app
-- /www
---- /assets
---- index.html
app.js
When I load assets/app.js in the browser I see the code inside index.html. Why is the static middleware being ignored?

express serves index.html even when my routing is to a different file

I have a public directory with the files index.html and index-08.html in it.
With the code below, I expect index-08.html to be served. But instead, index.html gets served with a browser request of localhost:3000
app.use(express.static(path.join(__dirname, 'public')));
app.get('/', function(req, res) {
res.sendFile('public/index-08.html');
});
But if I change the file name of index.html to something else, say not-index.html, then the correct file index-08.html gets served.
Can you please help me understand why this happens ?
This is because you declared app.use(express.static) before app.get('/'). Express checks routes in the order they are declared, and since index.html is a default filename which is used by static middleware, it shows index.html content.
To fix this you may either put app.use(express.static) after app.get('/'), or set index property of static second argument to non-existing file (false doesn't seem to work):
app.use(express.static(path.join(__dirname, 'public'), {index: '_'}));

Express: Redirect '/' to specific route

I'm asking for help after being unable to find a solution through other SO questions.
I'm doing some modular express app. This is the regarding part of my server.js file.
var app = express();
var login = require('./lib/login');
app.use(login);
app.use(express.static(path.join(__dirname, 'public')));
If I hit localhost:3000 It goes straight to public/index.html. But I want it to go to the login route. I've tried something like:
app.get('/', function(req, res){
res.redirect(__dirname + '/lib/login');
});
But it's not even being called since it always goes to index.html. Guess the line app.use(express.static(path.join(__dirname, 'public'))); is doing that from the get go. And Even if I comment that like for testing server's not redirecting to the route so I guess my code's not accurate.
I should add that inside the login route there's a jade template.
Any ideas?
More Information
Structure
/node_modules
/public
/javascripts
/stylesheets
/lib
/login
/views
server.js
Inside the public folder there's the index.html file that's being called. It's there just for testing, it has nothing to do with the real jade files I want to render.
I first added the app.use(express.static(path.join(__dirname, 'public'))); line so I can load my javascripts and my stylesheets in my jade templates with something like script(src='/javascripts/jquery.dataTables.js'). If I remove that original line from my server.js it DOES route / to login but then I can't seem to load those libraries inside javascripts and stylesheets, even if I change script(src='/javascripts/... to script(src='/public/javascripts/...

Resources