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.
Related
I've created a webpage to use it locally. I have a ton of routes like the ones shown below -- 31 .ejs files and 3 .html files. (They are all in the same "views" folder).
//app.js - using node and express
app.get('/page1', function(req, res){
res.render('page1');
});
app.get('/page2', function(req, res){
res.sendFile('views/page2.html', { root: __dirname });
});
I use an app.get for each and every one of these files. I've had a feeling it wasn't DRY code, and so now I'm trying to figure out a more elegant and optimal way to achieve the same result.
I know that many res.sendFile(); could be replaced with a single express.static() middleware statement. I usually use express.static() on a "public" folder which I use to save all my css files -- like this app.use(express.static(path.join(__dirname, 'public')));. But I still don't see how I could use this to simplify all my res.sendFile().
As for the many res.render(); routes, I know that if I don't pass any customized data I could probably replace them with a single middleware that handles either a whole directory of template files (and their corresponding routes) or a list of files. I just don't know how I would do that.
Any help is very much appreciated, thanks!!
[UPDATE]
richie node_modules public
css files, images, etc views
partials
all partial files programmingPublic
all ejs files from a same topic other files (html & other ejs) appjs
packagejson package-lockjson
const express = require('express');
const bodyParser = require('body-parser');
const path = require('path');
const app = express();
// Body Parser Middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
// engine
app.set("view engine", "ejs");
// Set static path
app.use(express.static(path.join(__dirname, 'public')));
const fs = require('fs');
function renderStatic(dir) {
return function(req, res, next) {
let target = path.join(dir, req.path);
fs.access(target, fs.constants.R_OK, function(err) {
if (err) {
// file not found, just move on
next();
} else {
res.render(target);
}
});
}
}
app.use(renderStatic(path.join(__dirname, "views/programmingPublic")));
Below is the format of my side-menu: (all these files are inside "programmingPublic" folder)
Programming
<li>C</li>
<li>C++</li>
<li>Python</li>
<li>JavaScript</li>
<li>PHP</li>
If you have a bunch of pages that need to call res.render(), but aren't passing custom options to each render, then you could isolate all those templates in their own directory and then use some middleware like this:
const path = require('path');
const fs = require('fs');
function renderStatic(dir, options) {
const regex = /^\.|\.\.|\/\.|\\\./;
options = options || {};
return function(req, res, next) {
let target = path.join(dir, req.path);
if (options.ext && !path.extname(target)) {
target = target + options.ext;
}
// don't allow leading dot or double dot anywhere in the path
if (regex.test(target)) {
next();
return;
}
fs.access(target, fs.constants.R_OK, function(err) {
if (err) {
// file not found, just move on
next();
} else {
res.render(target);
}
});
}
}
app.use(renderStatic(path.join(__dirname, "renderPublic"), {ext: ".ejs"}));
Note, you must isolate these template files in their own directory so that other files are not found there.
For safety completeness, this code also needs to filter out . and .. items in the path like express.static() does to prevent an attacker from going up your directory hierarchy to get access to other files than those in the render static directory.
Then, for the routes you are using res.sendFile() and no other logic, just isolate those HTML files in their own directory and point express.static() at that directory. Then, the express.static() middleware will find a matching HTML file in that directory and do res.sendFile() for you automatically, exactly the same as it does for your CSS files.
I have a basic project set up with server.js in my root with this code:
app.use('/', express.static(__dirname + '/public/'));
Additionally I have a public folder with index.html, styles and scripts folder in that dir root.
I'd like my web application to send users to index.html regardless of any url paramaters they might have. For example: If a user tries to go to localhost:8888/notarealpage it still loads index.html (without a redirect) so I can still reference the 'notarealpage' in the location.href property.
You can use:
app.get('*', function (req, res) {
res.sendFile(path.resolve(__dirname, 'public/index.html'));
});
This way, it will send your index.html no matter the URL.
Please notice you might have to fine tune the sendFile parameter.
Adding
app.get('*', function (req, res) {
res.sendFile((__dirname + '/public/index.html'));
});
to the end of my routes in server.js did the trick.
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
I was having trouble settings up a very basic static file sever using express with Node.js. I set up a simple server.js but cannot see any files when I load the URL localhost:9000 in my web browser.
All I see is a page saying: Cannot get /
var express = require('express');
var app = express();
app.use(function(req, res, next) {
next();
});
app.use(express.static(__dirname));
app.listen(9000);
Simply you're exposing nothing. Do you have, for example, an index.html file? Try this:
app.get("/", function(req, res) {
res.sendfile("index.html");
});
Did you go through the NodeSchool workshoppers? They have step-by-step examples that cover this and more.
Here is the workshop for Express.
Here is my solution for the 'static' question in the workshop.
var express = require('express')
var app = express()
app.use(express.static(process.argv[3]||path.join(__dirname, 'public')));
app.use(require('stylus').middleware(__dirname + '/public'));
app.post('/form', function(req, res) {
res.writeHead(200, { 'Content-Type': 'text/plain' })
res.end()
})
app.listen(process.argv[2])
Express does not create a directory listing. Even thought it does not list the files in the directory, it does serve them up when hitting them in the web browser.
Point the browser to the actual file:
http://localhost:9000/public/test.html
Originally I found this confusing because I had expected the express server to list directories; when seeing "something"... a page that said "Cannot get /" I assumed that page would normally have a list of files.
I am transitioning our site which is in a ASP environment and hosted on a Windows server.
The existing URL is
http://www.bruxzir.com/video-bruxzir-zirconia-dental-crown/index.aspx
But I need it to be
http://www.bruxzir.com/video-bruxzir-zirconia-dental-crown/
My app.js has this as the route
app.get('/video-bruxzir-zirconia-dental-crown/', function(req, res){
res.render('videos', {
title: 'BruxZir Video Gallery'
});
});
The new site will likely be hosted as a node.js app on heroku. Can I take care of this with an .htaccess ? if so, where would this be placed in an express app? and not all existing URLs have index.aspx only a few of them.
Many ways to get this to work, but here's one with a little middleware:
app.use(function (req, res, next) {
if (/index\.aspx$/i.test(req.path)) {
res.redirect(req.path.slice(0, req.path.length - 11));
return;
}
next();
});