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/...
Related
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 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.
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?
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: '_'}));
I want to use static file serve without any rendering engine.
I've tried to use:
res.sendfile('public/index.html');
on the '/' GET route, and express middleware for static files on my route:
app.use(express.static(path.join(__dirname, 'public')));
BUT it seems like all of the javascripts which the client asks for are downloaded with index.html file information.
How can I make a successful download of the CSS/JS static files ?
UPDATE:
Here is the route for the "res.sendfile ..." :
app.get('/*', index);
I want all of the requests to the server on any route will get index.html and all of its JS&CSS assosiciated with.
I guess this might help you...
in app.js file...
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
app.use("/styles", express.static(__dirname + '/public/stylesheets'));
app.use("/scripts", express.static(__dirname + '/public/javascripts'));
app.use("/images", express.static(__dirname + '/public/images'));
// development only
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
app.get('/', function (req, res) {
res.sendfile(__dirname + '/public/home.html');
});
save the home.html inside the /public folder and JavaScript files in /public/javascripts, images in /public/images, css files in /public/stylesheets folder.
In the HTML file reference should be the words you define(eg: /scripts/home.js)... like this
<link rel="stylesheet" type="text/css" href="/styles/home.css" >
<script src="/scripts/home.js" type="text/javascript"></script>
var express=require("express");
var app=express();
app.use('/', express.static(__dirname + '/website/views/'));
app.set("views",__dirname+'/website/views');
app.get("/",function(req,res){
res.sendfile('index.html');
});
the codes above is mine.i wish to help you.
Why not something like this?
if(req.url == '/') { // Root lookups appear to be mapped to index.html
next();
} else {
fname = [disk location of your website] + req.url;
fs.open(fname, 'r', function(err, fd) {
if(err) {
next();
} else {
fs.close(fd);
res.sendfile(fname);
}
});
}
Well, the simplest solution will be to move app.use(express.static(path.join(__dirname, 'public')))
up before you call app.use(app.router);
This way, the static middleware gets served before the app.get('/*', index);
I've made an assumption here that your routes are declared in this order:
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
If this is indeed the case, then the following suggestion holds:
The problem here is the app.get('/*', …) will intercept all requests that match, which is basically everything. Your static middleware won't get a chance at serving files.
If you remove that route, things should work for you as index.html is already in the public directory and can be served by the static middleware.
For a good explanation of how this works, see the answer to this question: node.js / express.js - How does app.router work?
Update based on additions to the above question:
You've stated this as the current behavior of your server:
it seems like all of the javascripts which the client asks for are downloaded with index.html file information.
You have asked the question:
How can I make a successful download of the CSS/JS static files ?
with this requirement
I want all of the requests to the server on any route will get index.html and all of its JS&CSS assosiciated with.
Your question and requirement are opposed to each other. The server will send back to the client exactly what you tell/configure it to. It will either always send back index.html which is exactly what your requirement states, or it will successfully serve up both index.html and any CSS/Javascript it references which is what your original problem statement was.
In one of your comments below you've stated:
the reason I want to do it, is because I'm using templates, and index.html wraps each template. I'm using angular on the client, and I'm starting to realize that i'll have to use a render engine in order to achieve this. Again, my angular client defines the partial url, and when it sends the request to : '/partial/sample' I need the index.html to wrap the 'sample.html' for instance
My assumptions based on this statement (please correct if wrong)
You are using client side templates
The files you are retrieving from the server are static (i.e., they need to be served up as is from the server)
Your routes are currently declared in this order
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
You are not doing any server side templating (i.e. everything is located under public somewhere)
If these assumptions are correct, the fix is to do what I originally suggested and remove this route:
app.get('/*', index);
If you do this (assuming your resources are referenced correctly):
your index.html will be retrieved as is from the server via the static middleware.
Each css/js file you've referenced in index.html will be returned from the server via the static middleware
Any requests to load template files (such as sample.html) will be serviced by your static middeware and returned to the client without modification