Cannot access static files through certain routes in nodejs - node.js

My routes are configured in app.js. The /users route works as expected except when rendering express layouts I cannot access the css files located at ./css/style.css
If I open a page using the /users route, I can see it's looking for /users/css/style.css but I thought setting the directory to static would override this?
app.use('/', require('./routes/index'));
app.use('/users', require('./routes/users'));
app.use(express.static('css'));

First of all, what app.use(express.static('css')); does is to serve statically the files starting from the given path, in this case css.
A good practice is to create a folder called public and use it to serve it's inner files statically. So your static folder should be like this:
-public
-css
-style.css
and your app.js should have app.use(express.static('./public'));
Now, another problem you may be having is the way you cast the paths (url) to load certain files.
Let's say you request http://localhost:PORT/users and the served HTML loads a stylesheet using <link rel="stylesheet" type="text/css" href="PATH">.
You could write the PATH in 2 ways.
css/style.css
/css/style.css
The difference is that the first method will search for the file relative to the path you're already in (e.g http://localhost:PORT/users/css/style.css). The other method will get such file using the 'domain' you are already in as a starting point (e.g http://localhost:PORT/css/style.css.
Hope this helps c:

I figured it out. Added this to my app.js file:
// GET /static/style.css etc.
app.use('/users', express.static(path.join(__dirname, 'public')))
More information here if needed: http://expressjs.com/en/api.html

Related

Express App Serving Unwanted Static Files

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

express does not include assets

I'm trying to load assets to my EJS file using express and it does not work. I just get message
Cannot GET /assets/main.css
Even I made loader in my main app:
app.use(express.static(path.join(__dirname, './assets')));
and after printing the path I see that its correct and the files exsists. So after using
<link href="assets/main.css" rel="stylesheet"> I can't reach the file. Where the problem could be?
See Serving static files in Express.
Right now, your app.use(...) statement is saying: I want the directory ./assets to be served whenever I navigate to my app, in other words, when I open my browser to http://localhost, serve whatever is in the folder ./assets.
You are then trying to access the file main.css at http://localhost/assets/main.css. It isn't there, it's at http://localhost/main.css.
You have 2 options:
Change your <link> tag to point to where the asset actually is:
<link href="main.css" rel="stylesheet">
Change your app.use() to host the ./assets folder at a different endpoint:
app.use('/assets', express.static(path.join(__dirname, './assets')));

It doesn't seem to be getting my index.html file in my views directory. I get an error on the localhost 3000, cannot get

You can view my files in github at https://github.com/elmoreka/myTaskLIst.git.
It doesn't seem to be getting my index.html file in my views directory. I get an error on the localhost 3000, cannot get .
The index.html is not served because the path used for res.render() is incorrect.
In your file routes/index.js, the rendered path is:
res.render('views/index.html');
However, as the view root is defined as myTaskList/views, the above code would try to find file myTaskList/views/views/index.html, which does not exist. To fix this issue, the rendered path need to be as:
res.render('index.html');
As per Expressjs, index.html is a normal static file in your case, that needs to be sent from the server and rendered at the client(browser). Since you haven't used any template engine (ejs) for your index page then the correct expressjs API to be used is
res.sendFile('index.html');
and not
res.render('index.html'); // this is not ejs template file.
In server.js you are defining "client" as your static folder:
// Set Static folder
app.use(express.static(path.join(__dirname, 'client')));
If you want to serve a static file like your index.html you need to move it to your static folder "client". Then you can send it to the client with res.sendFile().

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 static serving wrong path

I am messing around with express.js and have built some basic functionality but am having issues with express static serving from the wrong place if the URL is longer than one directory from root. See the examples below.
I am using the normal documented approach to using static.
app.use(express.static(__dirname + '/public'));
And have set up a couple of routes. eg.
app.get('/signup', function(req, res) {
res.render('signup.ejs');
});
With a 404 catch at the end of the chain.
app.get('*', function(req, res){
res.status(404).render('404');
});
If I hit page such as localhost:3000 or localhost:3000/login which are defined routes, all is well. Even if I hit an undefined route of localhost:3000/foo, I get the 404 rendered correctly with all images present.
However if I go one further and do something like localhost:3000/login/foo all the images are missing and I will get an error in the browsers console with the following address.
http://localhost:3000/login/img/site-brand.png
This happens the same on routes defined with more than one directory too.
I interpreted the docs on the express website that regardless of what was calling for the static image it would be served from the public directory in root, which contains a js, img, and css directories.
My questions are, what have I misinterpreted? and how do I get express to always serve relative to root?
I wrote the whole question then realised that when I had set up the src="" tags in my .ejs files I had used relative paths, not absolute. Rather than delete the question I decided to answer it and post it for others.
So instead of using src="img/my-image.png" it should be src="/img/my-image.png" The leading slash indicates that the request is relative to root not the path that is making the request.
Basic web development stuff there. I should have seen it first time out but its late, and I am cramming my head full of new frameworks which is in turn squeezing the more trivial stuff out of my small brain.

Resources