ExpressJS Serve static files within request function - node.js

I'm currently serving static files like this:
app.use('/javascripts', express.static(join(__dirname + '/assets/javascripts')));
and it works as expected.
What I would like to do is to use the user session to serve static files depending on the session. I've tried this:
app.use('/javascripts', (req: Request, res: Response, next) =>{
if(req.session.auth){
express.static(join(__dirname + '/auth/javascripts'))
} else{
express.static(join(__dirname + '/assets/javascripts'))
}
});
but it doesn't serve the files. Can someone explain why it doesn't work and how I can achieve what I'm trying to do?

A middleware function (the second argument of .use()) should process the request and call next(), so this code does nothing.
What you need is to just have a dynamic route (instead of middleware) that redirects to the correct static directory according to req.session.auth:
app.get('/javascripts/*', function(req, res){
if(req.session.auth){
res.sendfile(req.params[0], {root: './auth/javascripts'});
} else {
res.sendfile(req.params[0], {root: './assets/javascripts'});
}
});

Related

add parameter to request URL

I am serving a static file(.js) using script tag (due to webpack). So the request url is like http://localhost:8080/bundle.js But I want to add parameter to this request URL like this:
http://localhost:8080/bundle.js/abc
And according to parameter I will modify bundle.js and serve it.
But How can I add the params.
I'm not sure to understand your goal.
But if you use express to serve your bundle.js (as mentioned in the post tag), to use the parameters, you can do something like :
app.get("/bundle.js/:foo?", (req, res) => {
if (req.params.foo === "bar") {
res.sendFile(__dirname + "/src/bundle2.js");
} else {
res.sendFile(__dirname + "/src/bundle.js");
}
});
Here is a codesandbox with this example:
https://codesandbox.io/s/stackoverflow-74429869-7iz7l2?file=/app.js:242-435

Best way to handle dynamic routes with its own logic in ExpressJS?

I've been tasked with something at work that's beyond my current skills so any help is appreciated.
I'm building an admin where you can add "games". Each game needs to have it's own front-end, routes, and logic.
Kinda like,
mainsite.com/game/game1
mainsite.com/game/game2
mainsite.com/game/game3
At the moment I'm just creating a directory based on the game name.
var dir = "./games/" + req.body.gameId;
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir);
}
In turn I can pull the .ejs file via:
/* GET dynamic game page. */
router.get("/game/:game", function(req, res, next) {
res.render("../games/"+req.params.game+"/index", { title: "Express" });
});
But I am confused on how it can have it's own logic, routes, connecting to database, front-end, stylesheets inside it's own folder.
There must be a better way to achieve this right?
Cheers
Yes! In Express, you can call app.use() inside a route. You will be able to define a public folder to contain the CSS, JS, and assets that are specific to each route. Just call app.use(express.static('route/to/assets')) inside the route.
app.get('/game/:game', (req, res) => {
app.use(express.static(req.params.game + '/public'))
res.render('../games/' + req.params.game + "/index", { title: "Express" })
})
Seems strange, but perfectly allowed.

Expressjs remove static folder

I have nodejs webpage and i am using expressjs. I have few static folders and with user log out i have to remove some of them. Below is how i add static folder, i am not using any options maybe that is the problem.
app.use(express.static(__dirname + '/public'));
And i need something like below:
app.use(express.removeStatic(__dirname + '/public'));
or
app.use(express.static(__dirname + '/public',{vissible: false}));
As described here the express.static middleware is based on serve-static. There is no way of removing already loaded middleware (static files).
What I would suggest is creating your own serve-static middleware. You can use this as reference then just load the session middleware before the serve-static middleware then add an option that checks if the session data is available, if not then don't serve.
The basic idea is something like:
return function serveStatic(req, res, next) {
if (req.method !== 'GET' && req.method !== 'HEAD') {
return next()
}
// add this
if (req.session.loggedIn === false) {
return next()
}
Example
I have copied the serve-static code and added a condition to it, you can get it here.
Download it and save it as serve-static.js.
Include it in your expressjs project.
Modify to your use case.
Beware untested code.
Usage
var static = require('./serve-static')
// session middleware here
app.use(static(__dirname + '/public'));
This should only serve the static files when the req.session.loggedIn is true.
Of course you can change the condition to anything you want like:
if (req.session && req.session.ANYTHING_I_WANT === false && !!someMore) {
// skip all the code below (will not serve)
return next()
}
The condition can be found on line 64 of my serve-static gist.
Remember to add the session middleware before using the static middleware.
You can't remove static folders from express. What you can do is use res.sendFile to send a file as the response. For example:
app.get('public/:filename', function(req, res){
if(user.loggedIn) {
res.sendFile(req.params[:filename]);
} else {
res.status(402).send("Log in to access file");
}
})

Common Pre-Handler for ConnectJS/ExpressJS url handlers?

In my ExpressJS app, several of my urls handlers have the following logic:
See if the user has permission to access a resource
If so, continue
Else, redirect to the main handler.
Is there a way to insert a pre-handler for certain url handlers, via ConnectJS or ExpressJS?
I know I can do it globally, for all handlers, (which I do to insert missing headers as a result from IE's broken XDR).
But, can I do this for a subset of handlers?
I do something like this:
lib/auth.js
exports.checkPerm = function(req, res, next){
//do some permission checks
if ( authorized ) {
next();
} else {
res.render('/401');
return;
}
};
app.js
var auth = require('./lib/auth');
...
app.get('/item/:itemid', auth.checkPerm, routes.item.get);
You can stack middleware before your final route handler like the above line has. It has to have same function signature and call next();
If I understand this question correctly, you know about:
// This is too general
app.use(myAuthMiddleware());
And you are aware that you can add it manually to certain url-handlers:
app.get('/user/profile/edit', myAuthMiddleware(), function(req,res){
/* handle stuff */ });
// but doing this on all your routes is too much work.
What you might not know about express' mounting feature:
// Matches everything under /static/** Cool.
app.use('/static', express.static(__dirname + '/public'));
Or app.all():
// requireAuthentication can call next() and let a more specific
// route handle the non-auth "meat" of the request when it's done.
app.all('/api/*', requireAuthentication);

NodeJS + Express: How to secure a URL

I am using latest versions of NodeJS and ExpressJS (for MVC).
I usually configure my rest paths like this, for example:
app.get('/archive', routes.archive);
Now i want my /admin/* set of URLs to be secured, I mean I need just simple authentication, it's just a draft.
When a user tries to access, for example, /admin/posts, before sending him the corresponding view and data, I check for a req.session.authenticated. If it's not defined, I redirect to the login page.
Login page has a simple validation form, and a sign-in controller method: if user does send "right user" and "right password" I set the session variable and he's authenticated.
What I find difficult, or I don't understand, is how to actually make the "filter" code, I mean, the auth check, before every /admin/* path call.
Does this have something to do with "middleware" express functions?
Thank you
Yep, middleware is exactly what you want. A middleware function is just a function that works just like any other Express route handler, expept it gets run before your actual route handler. You could, for example, do something like this:
function requireLogin(req, res, next) {
if (req.session.loggedIn) {
next(); // allow the next route to run
} else {
// require the user to log in
res.redirect("/login"); // or render a form, etc.
}
}
// Automatically apply the `requireLogin` middleware to all
// routes starting with `/admin`
app.all("/admin/*", requireLogin, function(req, res, next) {
next(); // if the middleware allowed us to get here,
// just move on to the next route handler
});
app.get("/admin/posts", function(req, res) {
// if we got here, the `app.all` call above has already
// ensured that the user is logged in
});
You could specify requireLogin as a middleware to each of the routes you want to be protected, instead of using the app.all call with /admin/*, but doing it the way I show here ensures that you can't accidentally forget to add it to any page that starts with /admin.
A even simpler approach would be to add the following code in the App.js file.
var auth = function(req, res, next) {
if(isAdmin) {
return next();
} else {
return res.status(400)
}
};
app.use('/admin', auth, apiDecrement);
As you can see the middleware is being attached to the route. Before ExpressJS goes forward, it executes the function that you passed as the second parameter.
With this solution you can make different checks before displaying the site to the end user.
Best.
Like brandon, but you can also go the connect route
app.use('/admin', requireLogin)
app.use(app.router)
app.get('/admin/posts', /* middleware */)

Resources