Express: Index Route not called when index.html is served statically - node.js

node v5 express 4.13.3
What I did:
I was serving out the index.hmtl file when the index route("/") was hit. I then set it the public folder to be sent out as a static file.
What Problem it Caused:
Now that it is static, my index route is no longer entered when the browser opens the index route e.g.(localhost:3000/)
Question:
Is that expected behavior? Is it a good idea to serve index.html statically ?

Is that expected behavior?
Yes. Express will pass a request through the list of middleware (including your own index route), and if one of those can handle the request, it will and the request will finish (it won't get passed to other middleware).
The static middleware can handle the request for the index (presumably because you have an index.html in your public directory), so the request will end there and not get passed to your handler as well.
The order in which requests are passed to middleware is something that you can control. If you want your own index handler to get a higher priority, you should declare it before the static middleware:
app.get('/', function(req, res) {
...
});
app.use(express.static(...));
Is it a good idea to serve index.html statically ?
If it's plain HTML and there's nothing else that needs to be done when it's requested, it's probably best to let the static middleware handle it.

Related

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.

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.

How to prevent express server from serving api routes from the static folder

Hi I need some help with how express handles routes.
In setting up my express app, I have something like this:
app.use(express.static('public'));
Next, I mount some api routes:
app.use('/api', myrouter);
app.get('*', function(req, res) {
res.sendFile(path.resolve('public/index.html'));
});
But, when the frontend requests data via an api route, e.g. at 'localhost:3000/api/things', I am seeing in the Express debug logs that at some point (unsure when) it actually tries to serve this request as a static file, like:
send stat "C:\myproject\public\api\things" +230ms
Even though this folder doesn't exist in 'public' and should be solely handled by my api. FYI, the handler for /api/things route is only implemented for the GET method, and does get invoked at some point.
How do I stop express server from also trying to serve api requests from the static folder?
Thanks very much.
Answering my own question... which appears to be a duplicate of this one:
`express.static()` keeps routing my files from the route
So the answer is this one: https://stackoverflow.com/a/28143812/8670745
In short, the app.use() declarations that mount your api routers should appear before the app.use() statements which tell express.static where to serve your static files from. This way, the latter acts as a catchall AFTER api route handling is done. Router engine order matters...
Your answer is misinformed, or rather you've misinterpreted the problem. Your original configuration:
app.use(express.static(__dirname + 'public'));
app.use('/api', myrouter);
Looks absolutely fine because there's no clash between the routes. The threads you've linked too aren't really the same, and I can see why moving the routes in those cases would have worked.
The only thing I'd say is your path to your static folder isn't reliable, you should really use path.join, or actually in your case you can just do express.static('public') - express will infer the folder your app is served from.

Express middleware refrain static from going into next

I have the following function:
app.use('/Framework', express.static(path.resolve(__dirname, 'Framework')));
app.get('/*/*', function (req, res, next) {
...code...
);
The request goes into both the app.use and the app.get. I'd like it that when I try to access a resource with /Framework it just gives it to me as static while ignoring the other functions from below. Yet when accessing static it seems to go in the app.get.
Why is this happening and how can I modify it to get the wanted behavior?
Edit due to comment
I also have a
app.use('/Public', express.static(path.resolve(__dirname, 'Public')));
before which works perfectly as expected.
Requests such as : /Public/0.png work while requests such as /Framework/0.png enter both functions. I have checked the folders names over and over again and they are correct.
Express-static is Express middleware. Middleware is chained together and after a middleware is done executing its code, it calls next(); internally to allow the next middleware to execute. After all middleware is executed, the routes will be executed.
Since express-static calls next(); after its done, the routes will be invoked and checked if any routes match the request. Since your request /Public/0.png matches your route /*/* the route is executed.
My suggestion would be to try an rename your route from /*/* to something more specific.
You could try regex for the route which would explicitly allow any requests matching /*/* but would refuse any routes which have a file extension appended to it (i.e. /*/*.png).
Another (hacky) way would be to check for headersSent inside your /*/* route before executing the code within that route.
A side-note:
Seeing how your route name (e.g. Public and Framework) are the same as your directory names, you could simply do
app.use('/', express.static(path.resolve(__dirname, PARENT_DIRECTORY)));
Where PARENT_DIRECTORY is the parent directory of both Public and Framework. This way
Your directory structure would look like this:
Directory
|
| ---- Public
| ---- Framework
And any requests to Public would end up serving files from your Public directory, same for the Framework directory respectively.

How to use static folder but also use routing in Express?

I'm having a major issue with Routing in Express.
In my project, there is a folder /public.
Inside /folder I have some other folders like
- public
|- user
|- common
Initially, the only way pages were served by my Node.js server was through res.sendFile(../..). The problem was that the .js files and .css files did not know where to go.
So I added
app.use('/', express.static(__dirname + '/public'));
But now the problem is, if I try to visit /user what happens is, that the static version of the index.html file in that folder is returned, and my route defined in the node app is ignored!
This route - and most importantly the auth middleware is never touched!
How do I reconcile the need to serve files from a static folder, but also may have routes of the same name that I want to control more closely?
app.use('/user', userauth, userRoutes);
Assuming /user is some sort of API I don't think express.static was intended to be used that way. I think the best solution would be to use different routes. You could add something like /api/ to the beginning of all your routes or make sure your static files are organized under /css, /js, /partials, etc.
If you absolutely must support /user for static files AND your api calls you will need to ditch express.static and use something like the Accept header with custom middleware that determines what the browser is asking for. Depending on the scenario this may get complicated to support all the variables. A simple example would be something like this:
app.use(function(req, res, next){
// check Accept header to make sure its a JSON request
if(req.accepts('application/json') && !req.accepts('html')) {
// JSON request so forward request on to the next middleware(eventually hitting the route)
return next();
}
// NOT a JSON request so lets serve up the file if it exists...
// TODO use req.path to check if file exists - if not 404 - will also need to map paths
// to /users to check for /users/index.html if you need to support that
var fileExists = false;
return fileExists ? res.sendFile('...') || res.status(404).send('Not Found');
});
You would have to make sure when the client calls /users it sets the Accept header to application/json. Most client side frameworks have a way to do this for all AJAX requests.

Resources