I have a Node.js server which implements a set of base files that I want to serve as a default. Then other users of the server can require() it and overload some defaults and perhaps add additional files. For example:
server_base
/site
-> index.html 'A'
-> images 'A'
-> icon.jpg
user_server (requiring server_base)
/site
-> index.html 'B'
-> images 'B'
-> picture.jpg
The resulting website would have the merged set of those files with the user's index.html taking precedence over the base.
So far I've been trying to accomplish this with express since the use() method should allow for this hierarchy to be established.
server_base.js
var express = require('express'),
app = module.exports = express(),
server = null;
app.configure( function() {
server = require('http').createServer(app);
app.use('/', express.static(__dirname + '/site'));
server.listen(80);
});
user_site.js
var express = require('express'),
app = express(),
sb = require('../server_base');
app.configure( function() {
app.use('/', express.static(__dirname + '/site'));
app.use(sb); // server_base configure occurs here
});
As I understand it, if express finds a requested file in the first referenced root path (user_site's in this case) it should return that file. If not and its found in the other path, it should return that file (server_base). What I'm seeing though is that the '/' path is being totally wiped out with whatever the second call to use('/', ...) provided.
I figured perhaps it was the configure() call occurring twice and effectively wiping out settings. So I then tried exporting from server_base it's site path so that the user_site would app.use(...) it's own path followed by the server_base's. This results in a site somehow unable to serve any files.
I'm pretty new to Node.js and Express so if there is a better/cleaner way to make an easily-distributable and extendable server_base, I'm open to alternatives.
The order of the middlewares is important. You need to make your server base add it's static handler after the user has had time to add its static handler, something like this:
user_site.js:
var express = require('express'),
app = express(),
sb = require('./server_base');
app.use('/', express.static(__dirname + '/site'));
sb(app); // server_base configure occurs here
app.listen(8080);
server_base.js:
var express = require('express');
module.exports = function(app) {
app.use('/', express.static(__dirname + '/site'));
return app;
};
Related
I want to serve index.html and /media subdirectory as static files. The index file should be served both at /index.html and / URLs.
I have
web_server.use("/media", express.static(__dirname + '/media'));
web_server.use("/", express.static(__dirname));
but the second line apparently serves the entire __dirname, including all files in it (not just index.html and media), which I don't want.
I also tried
web_server.use("/", express.static(__dirname + '/index.html'));
but accessing the base URL / then leads to a request to web_server/index.html/index.html (double index.html component), which of course fails.
Any ideas?
By the way, I could find absolutely no documentation in Express on this topic (static() + its params)... frustrating. A doc link is also welcome.
If you have this setup
/app
/public/index.html
/media
Then this should get what you wanted
var express = require('express');
//var server = express.createServer();
// express.createServer() is deprecated.
var server = express(); // better instead
server.configure(function(){
server.use('/media', express.static(__dirname + '/media'));
server.use(express.static(__dirname + '/public'));
});
server.listen(3000);
The trick is leaving this line as last fallback
server.use(express.static(__dirname + '/public'));
As for documentation, since Express uses connect middleware, I found it easier to just look at the connect source code directly.
For example this line shows that index.html is supported
https://github.com/senchalabs/connect/blob/2.3.3/lib/middleware/static.js#L140
In the newest version of express the "createServer" is deprecated. This example works for me:
var express = require('express');
var app = express();
var path = require('path');
//app.use(express.static(__dirname)); // Current directory is root
app.use(express.static(path.join(__dirname, 'public'))); // "public" off of current is root
app.listen(80);
console.log('Listening on port 80');
express.static() expects the first parameter to be a path of a directory, not a filename. I would suggest creating another subdirectory to contain your index.html and use that.
Serving static files in Express documentation, or more detailed serve-static documentation, including the default behavior of serving index.html:
By default this module will send “index.html” files in response to a request on a directory. To disable this set false or to supply a new index pass a string or an array in preferred order.
res.sendFile & express.static both will work for this
var express = require('express');
var app = express();
var path = require('path');
var public = path.join(__dirname, 'public');
// viewed at http://localhost:8080
app.get('/', function(req, res) {
res.sendFile(path.join(public, 'index.html'));
});
app.use('/', express.static(public));
app.listen(8080);
Where public is the folder in which the client side code is
As suggested by #ATOzTOA and clarified by #Vozzie, path.join takes the paths to join as arguments, the + passes a single argument to path.
const path = require('path');
const express = require('express');
const app = new express();
app.use(express.static('/media'));
app.get('/', (req, res) => {
res.sendFile(path.resolve(__dirname, 'media/page/', 'index.html'));
});
app.listen(4000, () => {
console.log('App listening on port 4000')
})
If you have a complicated folder structure, such as
- application
- assets
- images
- profile.jpg
- web
- server
- index.js
If you want to serve assets/images from index.js
app.use('/images', express.static(path.join(__dirname, '..', 'assets', 'images')))
To view from your browser
http://localhost:4000/images/profile.jpg
If you need more clarification comment, I'll elaborate.
use below inside your app.js
app.use(express.static('folderName'));
(folderName is folder which has files) - remember these assets are accessed direct through server path (i.e. http://localhost:3000/abc.png (where as abc.png is inside folderName folder)
npm install serve-index
var express = require('express')
var serveIndex = require('serve-index')
var path = require('path')
var serveStatic = require('serve-static')
var app = express()
var port = process.env.PORT || 3000;
/**for files */
app.use(serveStatic(path.join(__dirname, 'public')));
/**for directory */
app.use('/', express.static('public'), serveIndex('public', {'icons': true}))
// Listen
app.listen(port, function () {
console.log('listening on port:',+ port );
})
I would add something that is on the express docs, and it's sometimes misread in tutorials or others.
app.use(mountpoint, middleware)
mountpoint is a virtual path, it is not in the filesystem (even if it actually exists). The mountpoint for the middleware is the app.js folder.
Now
app.use('/static', express.static('public')`
will send files with path /static/hell/meow/a.js to /public/hell/meow/a.js
This is the error in my case when I provide links to HTML files.
before:
<link rel="stylesheet" href="/public/style.css">
After:
<link rel="stylesheet" href="/style.css">
I just removed the static directory path from the link and the error is gone. This solves my error one thing more don't forget to put this line where you are creating the server.
var path = require('path');
app.use(serveStatic(path.join(__dirname, 'public')));
You can achieve this by just passing the second parameter express.static() method to specify index files in the folder
const express = require('express');
const app = new express();
app.use(express.static('/media'), { index: 'whatever.html' })
I want to serve index.html and /media subdirectory as static files. The index file should be served both at /index.html and / URLs.
I have
web_server.use("/media", express.static(__dirname + '/media'));
web_server.use("/", express.static(__dirname));
but the second line apparently serves the entire __dirname, including all files in it (not just index.html and media), which I don't want.
I also tried
web_server.use("/", express.static(__dirname + '/index.html'));
but accessing the base URL / then leads to a request to web_server/index.html/index.html (double index.html component), which of course fails.
Any ideas?
By the way, I could find absolutely no documentation in Express on this topic (static() + its params)... frustrating. A doc link is also welcome.
If you have this setup
/app
/public/index.html
/media
Then this should get what you wanted
var express = require('express');
//var server = express.createServer();
// express.createServer() is deprecated.
var server = express(); // better instead
server.configure(function(){
server.use('/media', express.static(__dirname + '/media'));
server.use(express.static(__dirname + '/public'));
});
server.listen(3000);
The trick is leaving this line as last fallback
server.use(express.static(__dirname + '/public'));
As for documentation, since Express uses connect middleware, I found it easier to just look at the connect source code directly.
For example this line shows that index.html is supported
https://github.com/senchalabs/connect/blob/2.3.3/lib/middleware/static.js#L140
In the newest version of express the "createServer" is deprecated. This example works for me:
var express = require('express');
var app = express();
var path = require('path');
//app.use(express.static(__dirname)); // Current directory is root
app.use(express.static(path.join(__dirname, 'public'))); // "public" off of current is root
app.listen(80);
console.log('Listening on port 80');
express.static() expects the first parameter to be a path of a directory, not a filename. I would suggest creating another subdirectory to contain your index.html and use that.
Serving static files in Express documentation, or more detailed serve-static documentation, including the default behavior of serving index.html:
By default this module will send “index.html” files in response to a request on a directory. To disable this set false or to supply a new index pass a string or an array in preferred order.
res.sendFile & express.static both will work for this
var express = require('express');
var app = express();
var path = require('path');
var public = path.join(__dirname, 'public');
// viewed at http://localhost:8080
app.get('/', function(req, res) {
res.sendFile(path.join(public, 'index.html'));
});
app.use('/', express.static(public));
app.listen(8080);
Where public is the folder in which the client side code is
As suggested by #ATOzTOA and clarified by #Vozzie, path.join takes the paths to join as arguments, the + passes a single argument to path.
const path = require('path');
const express = require('express');
const app = new express();
app.use(express.static('/media'));
app.get('/', (req, res) => {
res.sendFile(path.resolve(__dirname, 'media/page/', 'index.html'));
});
app.listen(4000, () => {
console.log('App listening on port 4000')
})
If you have a complicated folder structure, such as
- application
- assets
- images
- profile.jpg
- web
- server
- index.js
If you want to serve assets/images from index.js
app.use('/images', express.static(path.join(__dirname, '..', 'assets', 'images')))
To view from your browser
http://localhost:4000/images/profile.jpg
If you need more clarification comment, I'll elaborate.
use below inside your app.js
app.use(express.static('folderName'));
(folderName is folder which has files) - remember these assets are accessed direct through server path (i.e. http://localhost:3000/abc.png (where as abc.png is inside folderName folder)
npm install serve-index
var express = require('express')
var serveIndex = require('serve-index')
var path = require('path')
var serveStatic = require('serve-static')
var app = express()
var port = process.env.PORT || 3000;
/**for files */
app.use(serveStatic(path.join(__dirname, 'public')));
/**for directory */
app.use('/', express.static('public'), serveIndex('public', {'icons': true}))
// Listen
app.listen(port, function () {
console.log('listening on port:',+ port );
})
I would add something that is on the express docs, and it's sometimes misread in tutorials or others.
app.use(mountpoint, middleware)
mountpoint is a virtual path, it is not in the filesystem (even if it actually exists). The mountpoint for the middleware is the app.js folder.
Now
app.use('/static', express.static('public')`
will send files with path /static/hell/meow/a.js to /public/hell/meow/a.js
This is the error in my case when I provide links to HTML files.
before:
<link rel="stylesheet" href="/public/style.css">
After:
<link rel="stylesheet" href="/style.css">
I just removed the static directory path from the link and the error is gone. This solves my error one thing more don't forget to put this line where you are creating the server.
var path = require('path');
app.use(serveStatic(path.join(__dirname, 'public')));
You can achieve this by just passing the second parameter express.static() method to specify index files in the folder
const express = require('express');
const app = new express();
app.use(express.static('/media'), { index: 'whatever.html' })
I'm trying to get my express to serve up static files that are in another location:
This is the current directory I have:
|__client
| |__thumbnails.html
|
|__server
|__app.js
I tried to just use app.use(express.static(path.join(__dirname, '..', 'client')));, but it wouldn't serve the file at all. However, when I used the same path.join for a get request on '/' it will send the file.
Here it the code I have at the moment. It's working, thank God, but I want to see if there is a way for me to serve it without actually sending the file.
const express = require('express');
const path = require('path');
const similar = require('./routes/similar');
const image = require('./routes/images');
const app = express();
app.use(express.static(path.join(__dirname, '..', 'client')));
app.use('/item', similar);
app.use('/thumbnail', image);
app.get('/', (req, res) => res.status(200).sendFile(path.join(__dirname, '..', 'client', 'thumbnail.html')));
module.exports = app;
You can make the file anything you want, through configuration of the serve-static module:
https://expressjs.com/en/resources/middleware/serve-static.html
From that page:
var express = require('express')
var serveStatic = require('serve-static')
var app = express()
app.use(serveStatic('public/ftp', {'index': ['default.html', 'default.htm']}))
app.listen(3000)
now anything that you put in the 'index' array will be looked at, in the order you defined.
Otherwise, you would still be able to get to your html file if you put the actual filename in the url.
Okay I think I figured it out. So apparently you have to have the html saved as index. Express is looking for that, but since I don't have an index.html it skips my thumbnails.html.
So renaming my html to index.html fixed the issue.
UPDATE:
So reading through the documentation, you can set the what the default is by passing in an options. I passed in { index: 'thumbnails.html' } as the second argument for static and it serves my html.
Here I have one doubt, how can i pass value from node js app.js file to my client side js file.
Here My app.js file
var express = require('express');
var app = express();
var port = process.env.PORT || 3000;
var bodyParser = require('body-parser');
var facebookAppId = '123456789023'
app.configure(function() {
app.use(express.static(__dirname + '/dist'));
app.use(express.logger('dev'));
app.use( bodyParser.json() );
app.use( bodyParser.urlencoded() );
app.use(express.methodOverride());
});
app.listen(port);
Inside my dist folder i have index.html . that used to start run initially when i start app.js . So i would like to use the facebookAppId in my client side.How can i do that ?
Put it in it's own json file under a shared folder, then you can just require it like so in node:
shared/facebookInfo.json
{
"facebookAppId" : 123456789023
}
app.js
var facebookAppId = require('./shared/facebookInfo').facebookAppId;
...
// make sure to mount the directory as well so you can access it from the front end:
// it's being mapped to /shared here
app.use('/shared', express.static(__dirname + '/shared'));
...
And on the client side include it with ajax trough jquery or $http, whatever you are using.
A different approach could be to not put the file under a shared mounted folder, but include it during your front end build process.
This way you don't have to do an additional request to get in to your frontend and it's included more implicitly.
This is probably the most popular plugin to do that:
https://github.com/gruntjs/grunt-contrib-concat
This is off course somewhat assuming your frontend and backend are in the same repo. If they are in a different repo, you will have to put your shared data in a seperate repo as well, but that's a whole different question.
I am new to Express and semi-new to nodejs and I am trying to run a simple app / webserver as a proof of concept. I have been stuck for hours because my server serves every file as index.html (with the content of index.html).
In my index.html I am making calls to JS files and CSS files and they are all coming back but with a 200 in the console but they are all coming back with index.html content instead of the actual content contained in them. I believe the problem is in my server.js file which is below:
// server.js
// modules =================================================
var express = require('express');
var app = express();
var mongoose= require('mongoose');
var path = require('path');
// configuration ===========================================
// config files
var db = require('../config/db');
var port = process.env.PORT || 9999; // set our port
//mongoose.connect(db.url); // connect to our mongoDB database (uncomment after you enter in your own credentials in config/db.js)
app.configure(function() {
app.use(express.static(__dirname + '/public')); // set the static files location /public/img will be /img for users
app.use(express.logger('dev')); // log every request to the console
app.use(express.bodyParser()); // have the ability to pull information from html in POST
app.use(express.methodOverride()); // have the ability to simulate DELETE and PUT
});
// routes ==================================================
require('../../app/routes')(app); // configure our routes
// start app ===============================================
app.listen(port); // startup our app at http://localhost:9999
console.log('Magic happens on port ' + port); // shoutout to the user
exports = module.exports = app; // expose app
// app/routes.js
module.exports = function(app) {
// server routes ===========================================================
// handle things like api calls
// authentication routes
// sample api route
app.get('/api/nerds', function(req, res) {
// use mongoose to get all nerds in the database
Nerd.find(function(err, nerds) {
// if there is an error retrieving, send the error. nothing after res.send(err) will execute
if (err)
res.send(err);
res.json(nerds); // return all nerds in JSON format
});
});
// route to handle creating (app.post)
// route to handle delete (app.delete)
// frontend routes =========================================================
// route to handle all angular requests
app.get('*', function(req, res) {
res.sendfile('/Users/...../app/public/index.html'); // load our public/index.html file
//res.sendfile(path, {'root': '../'});
});
};
I have been following this tutorial verbatum: http://scotch.io/bar-talk/setting-up-a-mean-stack-single-page-application but haven't had much success.
I cannot confirm without looking at your computer but I get the feeling the paths in your application are wrong.
The crucial parts in the express setup are:
app.use(express.static(__dirname + '/public'));
and
app.get('*', function(req, res) {
res.sendfile('/Users/...../app/public/index.html');
The first rule catches and returns any static file in __dirname + '/public'.
The second returns index.html for anything else.
The problem is that your server.js is not in the apps directory (I can see this since you use ../../app/routes.js to get to routes.js) this means __dirname + '/public' is not pointing to the public directory. Which is why your static files are being served by the global rule in routes.js.
In order to fix this change __dirname + '/public' to ../../app/public, or better yet place your server.js file where it should be and update your paths.
I can also see you are using an absolute full path to index.html in routes.js instead of a relative one so it seems as if your applications needs to tidied out.
The tutorial that you are following contains this route
app.get('*', function(req, res) {
res.sendfile('./public/index.html'); // load our public/index.html file
});
which explicitly defines the behaviour you described.
In this tutorial it makes sense because it explains how to build a single page application. This type of the application typically returns the same content for all the request while the actual presentation work happens on the client by the client-side library (angular in this example).
So if you what to serve more pages with different content you need to add more routes for them, just like route for /api/nerds in the example.
Update:
After clarifying that the issue is incorrectly served CSS and JS files, the proposed solution is to check the location of the server.js - it should be in the folder together with the folder "public".