Node.js - How to hide html pages? - javascript

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.

Related

How to disable access to certain parts of an express server but be able to enable it later

I have a server that is fully functioning, but I only want it to be accessable when I say. I do this via a discord bot which works fine. I currently have a boolean variable server_on and an if (server on) { do } in all of my app.get and app.post functions. Is there a cleaner way to do this, or is this if statement in every function the only way?
Edit:
Final working code
var block_server_middleware = function (req, res, next) {
if (!server_on) { res.send("server is currently unavailable") }
else { next() }
}
app.use(block_server_middleware)
and the other app.get and app.post functions were not changed at all
This was the only few lines added that made the whole idea work
You can define one middleware function that goes before all your routes are defined:
app.use((req, res, next) => {
if (!server_on) {
// stop all routing
res.send("server not on!");
} else {
// let routing continue
next();
}
});
This will keep your routes from ever getting run until server_on is back to true. If you have any routes you want to leave open all the time, then just place them before this middleware.
You can replace res.send("server not on!"); with whatever is appropriate for your use. You can return a single web page or you can send back a 4xx or 5xx error status (perhaps a 503 error).

ExpressJS serve static files on post request

I need Express server to serve static files (website). It works in my code well:
var express = require('express');
var app = express();
var path = require('path');
var p = path.join(__dirname, '../web/public');
app.use("/files", function (req, res) {
return res.send("I will do something on server");
});
app.use(express.static(p));
app.use('/*',express.static(p));
let port = 80;
var server = app.listen(port);
But when I have a form served by this server, it redirects after submit, and the page displays only something like
Cannot POST /dashboard/
How can I correctly handle post requests within the meaning of serving static files? I tried to add this right before declaring the port:
app.post(express.static(p));
app.post('/*', express.static(p));
But it doesn't work.
PS: my entire page is served (I want that) from index.html. In order to do that, I have in my code that:
app.use(express.static(p));
app.use('/*',express.static(p));
How do I "redirect" post requests to index.html? In this file I have the entire app logic (it is a single page app).
PS2: I really need default submit. Going around that is not a solution for me (I want to offer the user to save their login and password, and without submitting the form, Google chrome will not offer that to users). And on the other side I really need use POST, as the login form is transferring sensitive data...
Any ideas?
Thanks!
There is no file called dashboard so there is nothing for express.static to serve.
To handle that dashboard route, you can do this:
app.post("/dashboard", function (req, res) {
return res.send("I will do something with this post");
});
If you want to redirect 404 traffic to index.html, you can do this after all your route definitions:
app.use("/", function (req, res) {
return res.redirect("/index.html");
});

nodejs: display an image not in public folder

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

Express - Serve different static folders on same route

Hello I would like to serve two different front-end applications on same route.
User will send a token in HTTP header and based on the information that token holds application should decide which folder should it serve statically. Is that possible?
I already have a middleware that parses token and provides me with user role.
Preferred behavior would be
module.exports = function (app) {
app.get('/admin' function(req, res) {
if(req.headers.security.role === 1) {
// serve superadmin page
} else if(req.headers.security.role === 2) {
// serve user page
} else {
// serve forbidden page
}
});
};
Of course it is, here is an example with a cookie sent with the request with nodejs.
app.get('*', function (request, response, next) {
let app = request.cookies.app;
if (app) {
response.sendFile(path.resolve(__dirname, 'app.html'))
} else {
response.sendFile(path.resolve(__dirname, 'app2.html'))
}
});

Express appears to be ignoring controller for root route

I am attempting to send all GET requests on my site (other than API requests) to a controller which checks for the presence of a signed-in user before showing the page. Otherwise, if not currently signed in, the user is sent to the sign-in page.
The below structure works perfectly for everything but the root route ('/'). For example, if I try to hit /admin or /games as a non signed-in user I am properly sent to the sign-in page. Likewise, if I am signed in each page shows properly (note: I am using AngularJS client-side). The one issue I have is that when I hit my root route the app attempts to show index.html without ever checking if the user is signed in. I'm confused as to why that route is handled differently, and why my pagesController is seemingly never invoked for this route. I've done some 'console logging' and confirmed that pagesController.index is called for each non-API route but '/'.
routes.js
'use strict';
var controllers = require('./controllers');
var v1Router = require('./routes/api/v1');
var pagesController = controllers.pagesController;
module.exports = function(app) {
app.use('/api', v1Router);
app.get('/logout', function(req, res) {
req.logout();
res.redirect('/');
});
app.get(['*'],
pagesController.index
);
};
pages.js
'use strict';
var path = require('path');
var index = function(req, res) {
if (req.user) {
res.sendFile(path.join(__dirname, '../assets', 'index.html'));
} else {
res.sendFile(path.join(__dirname, '../assets', 'signin.html'));
}
};
module.exports = {
index: index
};
Update: I changed my root from / to /a in my client-side routing and everything works perfectly. For whatever reason / is not being run through pagesController.index.
Update 2: So this line in my app.js is causing the issue:
app.use(express.static(path.join(__dirname, 'assets')));
With that line removed pagesController.index is properly called on /, however none of my static assets are served so simply removing that line does not solve it. How can I serve my static assets properly while ignoring index.html?
You can also handle the route in your conditional statements:
'use strict';
var path = require('path');
var index = function(req, res) {
if (req.user) {
res.sendFile(path.join(__dirname, '../assets', 'index.html'));
} if (req.url === '/') {
** Handle Case Here **
}
else {
res.sendFile(path.join(__dirname, '../assets', 'signin.html'));
}
};
module.exports = {
index: index
};
Ok, I did some research: A great article and possible solution here:(not sure if it fits your use case)
http://evanhahn.com/express-dot-static-deep-dive/
app.use(express.static(myStaticPath, {
index: ['jokes.txt', 'index.html']
})
You can simply give an array of files to serve as index, if the first is found it is served, if not, the second is served, and so on.

Categories

Resources