Express JS: how to know if request is for static asset? - node.js

I am writing middleware for some specific task, which should not be executed when request is for static assets (from client folder: app.use(express.static(path.join(__dirname, "../client")));)
So how can i know that particular request is for static asset or is being served from "client" folder?
I have below code
app.use(express.static(path.join(__dirname, "../client")));
app.use(someCustomMiddleware());
i am seeing that requests for static assets like for css/js files is still going thru someCustomMiddleware(). My requirement is that someCustomMiddleware() should not process request for static assets.

Just add it before your other routes. If a request is made for a static item then it will go to app.use(express.static(path.join(__dirname, "../client"))); first, and then your routes.
Ex. Let's say your public folder has some css folder with a file style.css in it. Let's say your routes look like this.
app.use(express.static(path.join(__dirname, "../public")));
app.use(someMiddleware);
If you access /css/style.css, it will hit express.static and serve the file, and will not go to that '/' route.

Related

Cannot access static files through certain routes in nodejs

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

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

I don't understand the logic of express.static(path.join(__dirname, 'public')))

I use this line
express.static(path.join(__dirname, 'public')));
Does it pass to the client post or get request?
Because if i use
express.get("/",function(res,req){
res.send(dataWirhDb);
}
There is no data on the client. If I use post request, I get data from the server.
If I use without
express.static(path.join(__dirname, 'public')))
and send to the client using get request, data is received on the client.
why does this happen?
No, express.static does not execute any requests. It's just a setup function that tells express that it needs to serve static files, and where to find them.
In this case the location is path.join(__dirname, 'public') , which means the public folder within your application directory.
The static files (like css, images, index.html etc.) are served automatically without the need of setting up routes for them. "Served" in this context means that the server sends the file back as a response to a GET request by the client, asking for that file.

Which headers indicate a request for static assets

Using Express we see middleware like so:
app.use('/', express.static(path.resolve(__dirname + '/public')));
app.use('/', function(req,res,next){
// if we get here, the request was not for static assets
});
my question is - which headers does Express use to check that the request is for static assets (files, etc)?
I want to replicate some middleware that does what Express does for static assets.
A typical HTTP request does not have any special headers that suggest that a client might be requesting a static asset over something else. In fact, there is concept of a 'static asset' in HTTP. HTTP is completely obviously to an asset being static, or not.
Anything can be 'static' or 'dynamic'. The middleware probably works because it will check the filesystem if a file exists.

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?

Resources