nodejs: display an image not in public folder - javascript

I would like to display an image which is not in the public folder in my webroot.
My hirarchy:
Webroot
--core
----views
----public <- Here is where stylesheets and other images are
------index.ejs <- Here I want to display the file.jpg
--data
----userdata
------username <- this folder is named by the user
--------assignment <- this folder is named by the assignment
----------file.jpg
I have no idea, i could move this into the public folder and rule it by the robots.txt, but I thought, maybe there is a better solution.

You can serve the data directory as a static directory, like your public directory -- Serving static files in Express. You'll probably want to set up some authentication middleware before the static route or everyone will be able to see each others data.
Here's an example of what that might look like:
// User authentication middleware
app.use(function(req, res, next) {
// Some implementation that determines the user that made the request.
req.username = 'foo';
next();
});
// Serve the public assets to all authenticated users
app.use(express.static('public'));
// Prevent users from accessing other users data
app.use('/data/userdata/{username}/*', function(req, res, next) {
if (req.username === req.path.username) {
next();
} else {
res.sendStatus(401); // Unauthorized
}
});
// Serve the data assets to users that passed through the previous route
app.use('/data', express.static('data'));

Related

Node.js - How to hide html pages?

I have html pages which shouldn’t be seen by the users who haven’t logged in. I used the command below and my html pages became public.
app.use(express.static('public'));
For example, I do not want users who are not logged in to see this page.
http://localhost:3000/admin.html
NOTE: what I'm talking about is not a cookie. When you enter the address of the html page in the toolbar, if it is not logged in, it should not be able to reach that page.
Create a custom static middleware, with the middleware you can validate the path(filename for this case).
I will try to explain with comments in a example code:
// path.join here makes it work cross platform with Windows / Linux / etc
var statics = express.static(path.join(__dirname, 'public'));
function secureStatic(pathsToSecure = []) {
return function (req, res, next) {
if (pathsToSecure.length === 0) {
return statics(req, res, next); // Do not secure, forward to static route
}
if (pathsToSecure.indexOf(req.path) > -1) {
return res.status(403).send('<h1>403 Forbidden</h1>'); // Stop request
}
return statics(req, res, next); // forward to static route
};
}
// add public files. List all "private" paths (file)
app.use(secureStatic(['admin.html'])); // instead of app.use(express.static('public'));
But, with this middleware, no one can request to admin.html file via you express server.

Node express change static folder on a user by user basis

Is it possible to do something like this with node and express middleware?
app.use('/',express.static('public'))
app.get('/public', function() {
app.use('/',express.static('public'))
})
app.get('/public2', function() {
app.use('/',express.static('public2'))
})
What i'm trying to accomplish is allowing users to have their own "public" directories to serve static files. the directory structure would be something like /user/< hash >
Think I have a solution for you!
app.get('/:user', function(req, res, next) {
app.use('/', express.static(path.join(__dirname, 'public/' + req.params.user)));
res.send('');
});
To explain, imagine the two files at the paths:
/__dirname/public/user1/userdata.text
/__dirname/public/user2/userdata.text
By visiting the following two URLs:
http://localhost:3000/user1/userdata.txt
http://localhost:3000/user2/userdata.txt
You'd be requesting those two different files respectively. If the file doesn't exist, it throws a 404 like you'd expect!
Hope this helps.

In Express.js, how do I set a wildcard route to not match for asset files?

I'm building my first real Express.js app, and stuck on the routing.
I am enabling static hosting:
app.use("/", express.static("public"));
And then I have a wildcard route:
router.get("/:page", function(req, res) {
// do stuff
});
This route is matching for urls like "/about" and "/contact" - which I want. But it appears that it's also trying to match for "/style.css" and other static asset files - which is unnecessary.
How do I make this wildcard not match for asset files?
One solution I found, is to search for a "." inside the query and then set a flag if it's found:
router.get("/:page", function(req, res) {
if (req.render_view) res.render("index");
});
router.param("page", function(req, res, next, page) {
// if request is not an asset file
if (page.indexOf(".") == -1) {
// do stuff
// set a flag
req.render_view = true;
}
next();
});
But I would like to find a cleaner solution, possibly using a regular expression in the router.get?
if I understand what you want to do ,you should just do something like :
app.js
app.use(express.static(__dirname + '/public'));
app.use(express.static(__dirname + '/static'));
app.use('/:page',function(){}..)
this configuration works when ur public and static folder is relative to app.js, when browser request for static file , first server will look at public folder , if file is no there will continue to static folder and finally to /:page

express.js unique directory for each user

I have an express.js app, and I am using drywall in order to manage the user system.
When a user signs up, I want a directory to be generated for that user, and I want that user to be able to upload files to that directory and view those files through his or her account.
I am not entirely sure, but I think that most likely for the directory generation I will have to do that inside views/signup/index.js, and that the user can only upload files to his or her directory if logged in.
However, I'm a bit stuck when it comes to saving and displaying the files. I have little experience with server side code, so implementing actions such as accessing files is slightly beyond my scope.
Thanks in advance to those who help.
So first you should create a folder for each user by using fs.mkdir:
http://nodejs.org/api/fs.html#fs_fs_mkdir_path_mode_callback
Let's say you want to create these folders into your app root / images:
Example:
var fs = require('fs');
fs.mkdir(__dirname + '/images/' + userId, function(err) {
if (err) {
/* log err etc */
} else {
/* folder creation succeeded */
}
});
You should probably use the userId for the folder name (since it's easier than trying to strip out the bad characters from the username itself, and this will also work in the future if the user changes his username).
The second thing you need to do is to allow the user to upload files (but only if he is logged in and into the right folder). It's better to not include the bodyParser middleware for all routes, but instead include the json && urlencoded middleware for all routes (http://www.senchalabs.org/connect/json.html && http://www.senchalabs.org/connect/urlencoded.html) and the multipart middleware only for the upload url ( http://www.senchalabs.org/connect/multipart.html && example: https://github.com/visionmedia/express/blob/master/examples/multipart/index.js ).
An example:
app.post('/images', express.multipart({ uploadDir: '/tmp/uploads' }), function(req, res, next) {
// at this point the file has been saved to the tmp path and we need to move
// it to the user's folder
fs.rename(req.files.image.path, __dirname + '/images/' + req.userId + '/' + req.files.image.name, function(err) {
if (err) return next(err);
res.send('Upload successful');
});
});
Note: in the example above I've taken into consideration that req.userId is populated with the id of the user by an auth middleware.
Showing the images to the user if he has the rights to see them (the auth middleware should be applied for this path as well):
app.get('/images/:user/:file', function(req, res, next) {
var filePath = __dirname + '/images/' + req.userId + '/' + req.params.file;
fs.exists(filePath, function(exists) {
if (!exists) { return res.status(404).send('Not Found'); }
// didn't attach 'error' handler here, but you should do that with streams always
fs.createReadStream(filePath).pipe(res);
});
});
Note: in production you might want to use send instead, that example was just demoing the flow ( https://github.com/visionmedia/send ).

Custom handler in express.js router

I'm working for simple meal info page, and I need to run static and dynamic (json) server in one process, like this:
*- root
+- index.html
+- res
| +- main.js
| +- index.css
| `- (and more)
+- meal
| `- custom handler here (json reqestes)
`- share
`- (static files, more)
static files will handled with express.static, Can I route this with express?
all requests without starts with /meal/ should served as static, like /res or (root)/anyfolder/anyfile
app.use('/share', express.static('share')); makes the static handler look in share/, not the project root. It's unusual to share the whole root because people can read your source code. Do you really need to serve the whole folder? Can you e.g. put res/ inside share/, and then make a symlink pointing res -> share/res/, then when a client makes a request res/main.js express knows to look in share/res/main.js.
Anyway #hexacyanide's code should handle your case, just make sure to order your middleware functions such that Express handles routing functions before static files:
app.use(app.router)
app.use('/share', express.static('share'));
app.get('/meal/:param', function(req, res) {
// use req.params for parameters
res.json(/* JSON object here */);
});
// if you want to prevent anything else starting with /meal from going to
// static just send a response:
//app.get('/meal*', function(req, res){res.send(404)} );
app.get('/', function(req, res) {
res.sendfile('index.html');
});
Yes, this can be done with Express. Your setup might look like this:
app.use('/share', express.static('share'));
app.get('/', function(req, res) {
res.sendfile('index.html');
});
app.get('/meal/:param', function(req, res) {
// use req.params for parameters
res.json(/* JSON object here */);
});
Where you have a static file server mounted to /share and routed to the directory called /share, a route at / which sends the file called index.html, and a route that accepts a parameter, that responds with JSON.
Anything that isn't caught by a route will be attempted to be processed by the static file server. If the file server doesn't find a file, then it will respond with a 404.

Categories

Resources