Express.js - any way to display a file/dir listing? - node.js

With Express.js is there a way to display a file/dir listing like apache does when you access the URL of a directory which doesn't have a index file - so it displays a listing of all that directories contents?
Is there an extension or package that does this which I don't know of? Or will I have to code this myself?

As of Express 4.x, the directory middleware is no longer bundled with express. You'll want to download the npm module serve-index.
Then, for example, to display the file/dir listings in a directory at the root of the app called videos would look like:
var serveIndex = require('serve-index');
app.use(express.static(__dirname + "/"))
app.use('/videos', serveIndex(__dirname + '/videos'));

There's a brand new default Connect middleware named directory (source) for directory listings. It has a lot of style and has a client-side search box.
var express = require('express')
, app = express.createServer();
app.configure(function() {
var hourMs = 1000*60*60;
app.use(express.static(__dirname + '/public', { maxAge: hourMs }));
app.use(express.directory(__dirname + '/public'));
app.use(express.errorHandler());
});
app.listen(8080);

The following code will serve both directory and files
var serveIndex = require('serve-index');
app.use('/p', serveIndex(path.join(__dirname, 'public')));
app.use('/p', express.static(path.join(__dirname, 'public')));

This will do the work for you: (new version of express requires separate middleware). E.g. you put your files under folder 'files' and you want the url to be '/public'
var express = require('express');
var serveIndex = require('serve-index');
var app = express();
app.use('/public', serveIndex('files')); // shows you the file list
app.use('/public', express.static('files')); // serve the actual files

Built-in NodeJS module fs gives a lot of fine-grained options
const fs = require('fs')
router.get('*', (req, res) => {
const fullPath = process.cwd() + req.path //(not __dirname)
const dir = fs.opendirSync(fullPath)
let entity
let listing = []
while((entity = dir.readSync()) !== null) {
if(entity.isFile()) {
listing.push({ type: 'f', name: entity.name })
} else if(entity.isDirectory()) {
listing.push({ type: 'd', name: entity.name })
}
}
dir.closeSync()
res.send(listing)
})
Please make sure to read up on path-traversal security vulnerabilities.

How about this code?
Simple and can download files.
I found in here.
var express = require('express')
var serveIndex = require('serve-index')
var app = express()
// Serve URLs like /ftp/thing as public/ftp/thing
// The express.static serves the file contents
// The serveIndex is this module serving the directory
app.use('/ftp', express.static('public/ftp'), serveIndex('public/ftp', {'icons': true}))
// Listen
app.listen(3000)

Related

Run HTML file on HTTPS local server [duplicate]

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' })

how to access images on disk on localhost and access via url on website [duplicate]

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' })

Serve static files and directory listing in LoopBack

Following a LoopBack tutorial, I want to modify it to serve a directory listing if the directory does not have an index.html or similar.
I have previously done this in Express using:
var express = require('express');
var serveIndex = require('serve-index');
var app = express.express();
app.use('/', serveIndex(__dirname + '/public', {}));
app.use('/', express.static('public'));
Can I modify middleware.json to do this? Alternatively, how could I do this in a LoopBack JS boot script?
I have tried putting the following in a file routes.js in the boot directory:
module.exports = function(app)
{
var serveIndex = require('serve-index');
app.use('/', serveIndex(__dirname + '../client', {}));
app.use('/', app.static('../client'));
};
But it's obviously not the same, since app.static() in the first example is not a method on the same object as use() - ie the second example produces the error:
TypeError: app.static is not a function
(Also the paths aren't right, but I'm dealing with one problem at a time)
It was quite straightforward. While I could not find a way to access the express module via the loopback app object, it could simply be require()d.
Create the file ./server/boot/routes.js with the following:
module.exports = function(app)
{
var express = require('express');
var serveIndex = require('serve-index');
var croot = __dirname+'/../../client';
app.use('/', express.static(croot));
app.use('/', serveIndex(croot, {'icons': true}));
}

Node.js Serve-static not working

I'm having some trouble with routing and serving static files.
My directory structure is like this:
app/
--app.js
—-public/
—-js/
—-main.js
—-views/
—-pages/
—-index.jade
This is how I've set up my server:
app.js
var express = require('express')
var path = require('path')
var serveStatic = require('serve-static')
var publicPath = path.join(__dirname,'..','public');
var port = process.env.PORT || 3000
var app = express()
app.set('views', './views/pages')
app.set('view engine', 'jade')
app.use('/public', serveStatic(publicPath));
app.listen(port)
console.log("port is " + port)
app.get('/', function(req, res) {
res.render('index', {
title: 'index',
})
})
index.jade
doctype
html
head
meta(charset="utf-8")
title index
script(src="/public/js/main.js”)
body
h1=title
But this is what happens when I visit the index:
GET http://localhost:3000/public/js/main.js 404 (Not Found)
How do I set up the "serve-static" part to work?
Thanks!
you are passing the wrong parameter to it.
correct example for serving static files from different directory would be
This example shows a simple way to search through multiple directories. Files are look for in public-optimized/ first, then public/ second as a fallback.
var express = require('express')
var serveStatic = require('serve-static')
var app = express()
app.use(serveStatic(__dirname + '/public-optimized'))
app.use(serveStatic(__dirname + '/public'))
app.listen(3000)
check out the docs for more options https://github.com/expressjs/serve-static
I think you need to remove public from the path.
script(src="/js/main.js”)
You're telling the server static resources are served from the public folder.

Run NodeJS app on nodejitsu, all i get is "cannot get /"

as part of my learning i wanted to deploy my app to nodejitsu. Its running fine on my local server, but on nodejitsu all i get is
Cannot GET /
I thought it may have something to do with the NODE_ENV set to production on the server, but i never touched this on my local server. I changed it on nodejitsu to development but still i cant get it to work.
After commenting all the code i think the problem is in my index.js which i show below:
var express = require('express');//the framework
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
//var session = require('express-session');
var methodOverride = require('method-override');
var passport = require("passport");//for authentication
var LocalStrategy = require('passport-local').Strategy;//local users for passport
var http = require('http');
var path = require('path');
var db = require('./dataBase');//to connect to the db
var userRoles = require('./routingConfig').userRoles;
var accessLevels = require('./routingConfig').accessLevels;
var debug = false;
var db = new db('inmobiliaria', 'localhost', 3306, debug);
require('./passport')(passport, db, debug)
var app = express();
app.set('port', 1337);
app.use(methodOverride());
app.use(cookieParser());
app.use(bodyParser.urlencoded({ extended: false }))
//app.use(session({ secret: 'SECRET' }));
app.use(passport.initialize());
app.use(passport.session());
app.use(function (req, res, next) {
var role = userRoles.public;//default role
var username = '';
if (req.user) {
role = req.user.role;
username = req.user.username;
}
res.cookie('user', JSON.stringify({
'username': username,
'role': role
}));
next();
});
app.use('/', express.static(path.join(__dirname + '/../Client/')));
app.use("/lib", express.static(path.join(__dirname + '/../Client/lib/')));
app.use("/ctr", express.static(path.join(__dirname + '/../Client/Controllers/')));
app.use("/media", express.static(path.join(__dirname + '/../Client/media/')));
app.use("/views", express.static(path.join(__dirname + '/../Client/Views/')));
app.use("/srv", express.static(path.join(__dirname + '/../Client/Services/')));
app.use("/dct", express.static(path.join(__dirname + '/../Client/Directives/')));
require('./routes')(app, passport, db);
//require('./emailConfiguration');
http.createServer(app).listen(process.env.PORT || app.get('port'), function (err) {
console.log("Express server listening on port " + app.get('port'));
if (err) {
throw err; // For completeness's sake.
}
});
I investigated about this variable, but im not sure it has something to do with it. This is the url http://horaciotest.jit.su/, in case you want to see it.
Is this configuration? Am i doing something that should not be done?
Thanks for taking your time.
EDIT:
i managed to reduce the error case to a few lines i think. As the guys at nodejitsu suggested, im now trying to use the module node-static to serve static files, but i cant get it to work along express:
this code works on nodejitsu and my local server (or at least doesnt show any errors)
var statik = require('node-static');
var http = require('http');
var path = require('path');
var file = new (statik.Server)(path.join(__dirname + '/../Client/'));//index.html here
http.createServer(function (req, res) {
console.log(path.join(__dirname + '/../Client/'));
file.serve(req, res);
}).listen(8080);
but as soon as i add express, i get the error i mentioned above:
var express = require('express');
var statik = require('node-static');
var http = require('http');
var path = require('path');
var app = express();
var file = new (statik.Server)(path.join(__dirname + '/../Client/'));//index.html here
http.createServer(app, function (req, res) {
console.log(path.join(__dirname + '/../Client/'));
file.serve(req, res);
}).listen(8080);
Can someone tell me why when i add the express app i get the error? it may be what i need to get this to work on nodejitsu, thanks!
I found out what the problem was, hope it helps someone:
My project structure had two folders: one was named Client, where all my html and .js from angular where.
The other folder was WebServer, where i had all my nodejs files.
In order to deploy to nodejitsu, you run a command which is jitsu deploy, this in turn runs another command: npm pack. This command creates a .tgz file with all the data in you nodejs directory excluding the node_modules file and any file that starts with .. Problem is, if you like me have files outside that folder, they wont be included.
The solutions is to move your client folder inside the nodejs one. Everything you need to sent to the server should be in side this folder.

Resources