I'm trying to get express static working with dynamic subdomain.
Basically http://ratty-doll-4811.localhost:3333 this subdomain is dynamic, and I load static folder based on this subdomain.
My issue is index.html loads but app.js which is in the same directory as index.html, doesn't load.
const subdomain = require('subdomain');
var app = Express()
app.use(subdomain({ base : 'localhost', removeWWW : true }));
app.get('/subdomain/:url', function(req, res, next) {
app.use('', Express.static(path.join(__dirname, 'public')));
res.sendFile('index.html', { root: __dirname + '/public' })
});
Here is the error:
You can't dynamically call app.use() because that will just build up route handlers over and over and they will accumulate indefinitely and be in force for all future requests. You can however, get the request handler from express.static() and call the request handler yourself dynamically.
I don't follow exactly what you're trying to accomplish, but this will show you how you can call it dynamically and then act differently based on whether it found a match of not.
// get express.static() handler
let staticHandler = Express.static(path.join(__dirname, 'public'));
app.get('/subdomain/:url', function(req, res, next) {
staticHandler(req, res, (err) => {
if (err) return next(err);
// it only gets here if the staticHandler didn't find a match and send a response
res.sendFile('index.html', { root: __dirname + '/public' })
});
});
Related
I am trying to create an SPA using Express with following code
var express = require('express');
const path = require('path');
var app = express();
app.use('/assets', express.static(path.resolve(__dirname, 'www', 'assets')));
app.get('/*', (req, res)=>{
res.sendFile(path.resolve('www', 'index.html'));
});
var server = app.listen(3000, function(){});
This code works good but the problem is this responds with my index.html even when a file is not found in my assets folder. I want it to respond with error of 404 Not Found if some url is not present in assets folder
I tried using this code after line app.use('/assets'...
app.use(function (req, res, next) {
res.status(404).send("404 Not Found");
});
but not working
Issue is with
app.get('/*', (req, res)=>{
res.sendFile(path.resolve('www', 'index.html'));
});
Instead, use
app.get('/', (req, res)=>{
res.sendFile(path.resolve('www', 'index.html'));
});
So, I finally got the way to solve it
app.get('/*', (req, res)=>{
if(req.path.includes('/assets'))
{
fs.access(req.path, (err) => {
if(err)
{
res.status(404).send("Sorry can't find that!");
return;
}
});
}
res.sendFile(path.resolve('www', 'index.html'));
});
In the code, I have told to check if the request is about a file located in assets folder then check if the file exists, if does not exists then send 404 error with message and just return, otherwise do nothing but return the file.
I'm fairly new to node.js and trying to make a simple website which first asks the authentication and then redirects the user to a page.
so, what i do is that i create a middleware which listenes to every request made to my website.
what this middleware does that it checks if the the user is logged in with my website or not is yes then redirect to the requested page if not, then redirect to the login page, here is my code for that.
var express = require('express');
var app = express();
// middleware for using static files
app.use('/public', express.static(__dirname + '/public')); // all the js files for check_before.html
app.use('/templates', express.static(__dirname + '/templates')); // here are css/js files for login.html
// setting up views folder
app.set('views', __dirname + '/views'); // check_before.html is sitting here
app.engine('html', require('ejs').renderFile);
app.set('view engine', 'html');
app.use((req, res, next) => {
res.render('check_before.html');
// here in the html I implement the logic using js files which are located in public folder.
next();
});
// if not logged in , the user gets here
app.get('/login', (req, res, next) => {
res.render('login.html')
});
// if logged in redirect to some page
app.get('/welcome_page', (req, res) => {
return 'welcome'
});
everything goes well untill the user hits the http://localhost:8000/login page (after the check if they are signed in or not) the page keeps on loading multiple times and it won't stop reloading.
I have defined all the css, js files of login.html page in the templates folder which is loaded above the middleware by reffereing to this question
Express middleware getting called many times. could that be a problem?
what could be the reason for this?
here is the error i'm getting in the console.
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
any guesses?
Edit1
I went through this question Error: Can't set headers after they are sent to the client , and i guess it concludes that setting headers explicitly could be problematic.
Could this be a reason? because in my logic if the user is not signed In, I'm just using window.location.replace('http://localhost:8000/login') to redirect the user to login page.
should I use any another method for redirection?
Edit2
There are suggestions that i must write a middleware to check is the user is authenticated or not, and get a sort of flag for that, but as i've stated above that i'm implementing the logic in check_before.html(client side). so it won't be possible to use that.
I have two guesses:
You shouldn't call send (or any other function )after res.render.
Middleware to verify user is logged in should be something like this (applied only to routes you want to verify user)
Middleware should be something like this
const isAuthenticated = (req, res, next) => {
if(req.isAuthenticated()) {
next();
} else {
res.redirect('/');
}
}
app.get('/welcome_page', isAuthenticated, (req, res) => {
return 'welcome'
});
The reason is that middleware is called before your /login request. To fix it, you need to modify your middleware function. It should be something like:
app.use((req, res, next) => {
if(isLoggedIn) { //isLoggedIn is a flag that checks whetehr user is logged-in or not
res.render('check_before.html');
} else {
// here in the html I implement the logic using js files which are located in public folder.
next();
}
});
I have an Angular app running alongside a NodeJS server.
This code in my server.js file:
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'dist/index.html'));
});
require('./server/routes/routes')(app, passport);
Seems to be preventing any GET requests to my api, for example:
module.exports = function (app, passport) {
app.get('/api/profile', isLoggedIn, function (req, res) {
res.status(200).json(req.user);
});
When the exported /api/profile handler is changed to a post the request works.
Should the route not overwrite the initial handler? How to achieve this? Can I serve the app for all routes excluding beginning with '/api'?
Move the app.get('*') so it becomes the last route that gets declared:
require('./server/routes/routes')(app, passport);
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'dist/index.html'));
});
Express checks route handlers in order of their declaration, not in order of their specificity (how well they match a particular request).
I am getting the below screen-shot error when I try to serve my client-side code. When I am trying to run node server/server.js:
The below is my server.js code...
app.use(express.static(path.join(__dirname, "public")));
app.use(logger('dev'));
app.use(bodyParser.json({limit: '50mb'}));
app.all('/*', function(req, res, next){
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE, OPTIONS");
res.header("Access-Control-Allow-Headers", "Content-type,Accept,X-Access-Token,X-Key");
if(req.method === 'OPTIONS'){
res.status(200).end();
} else {
next();
}
});
app.all("/api/v1/*", [require('./middlewares/validateRequest')]);
app.use("/", require("./routes"));
app.use(function(req, res, next){
var err = new Error("Not found");
err.status = 404;
next(err);
});
Inside my routes/index.js, I have the following for get request.
router.get('*', function(req, res) {
res.sendfile('./public/index.html');
});
Usually when the browser requests a JavaScript file, the server sends an HTML file. This is due to rules like app.get('*'.... So we need to tell the server to send the static files first and then declare the rules, like shown below:
// Declare static folder to be served. It contains the JavaScript code, images, CSS, etc.
app.use(express.static('build'));
// Serve the index.html for all the other requests so that the
// router in the JavaScript application can render the necessary components
app.get('*', function(req, res){
res.sendFile(path.join(__dirname + '/build/index.html'));
//__dirname : It will resolve to your project folder.
});
My folder structure
node(folder)
server.js
-client(f)
-index.html
-views(f)
-js(f)
-ctrl(f)
-service(f)
-app.js
-state.js
and
app.use(express.static('client'));
app.get('/index.html', function (req, res) {
res.sendfile(_dirname + '/index.html');
});
Call this from the browser: http://127.0.0.1:1956/index.html
var server = app.listen(1956, function (req, res) {
var host = server.address().address
var port = server.address().port
console.log("app listening at", host, port)
});
It's working fine for me.
I think this may be caused by your /public/index.html file.
When you include the JavaScript files in the index.html file, there's some problem with the "src" property. Thus it will return a "not found" HTML file instead of the actual JavaScript file.
I found the solution. The Node.js application tries to compile the JavaScript files inside the public folder, that makes a mistake; you defined the public folder like this:
app.use(express.static(path.join(__dirname, 'public')));
Try to define it using a virtual directory by adding a specific virtual folder name like this:
app.use('/static', express.static(path.join(__dirname, 'public')));
This should be work;
I guess part of the problem is in your router
In your routes/index.js change the get request to
router.get('/', function(req, res) {
res.sendfile('./public/index.html');
});
Also are you pipe-lining your assets using gulp or something similar? If not then how are you serving your assets?
I recommend you either serve your assets statically or use gulp
I have a bunch of html files that I want to serve as static files. However, I need the routes to not have any .html in it.
When the route is
example.com/about
it should serve about.html
The research I did on serving static files seems to suggest that it is not entirely possible. Is that right, or am I missing something?
You need to serve your static file using the router
app.get('/about', function(req, res) {
res.render('about.html');
});
Before that you should setup a middleware for the html rendering engine
Or if you have a lot of static files, you could use a middleware to do it for you
https://www.npmjs.com/package/clean-urls
You can create a short little piece of middleware that will process whichever preset names you configure it for. Anything not in that list will go to your normal routes:
// create static file lookup table for the desired names
var staticFiles = ["about", "index", "home"].reduce(function(obj, item) {
obj["/" + item] = true;
return obj;
}, {});
app.use(function(req, res, next) {
// if the path is found in the lookup table, then
// add ".html" onto the end and get that file from the base directory
// of you could use any source directory for those files
if (staticFiles[req.path]) {
res.sendFile(path.join(__dirname, req.path + ".html"));
return;
}
next();
});
Note: this very carefully only serves specific files so nobody can go snooping around in your file system with other types of URLs.
Here's an example where the files are served from a subdirectory below our base directory named "html":
app.use(function(req, res, next) {
if (staticFiles[req.path]) {
res.sendFile(path.join(__dirname, "html", req.path + ".html"));
return;
}
next();
});
In node v0.12+, you can use the Set object for your list of static routes like this:
var staticFiles = new Set(["/about", "/index", "/home"]);
app.use(function(req, res, next) {
if (staticFiles.has(req.path)) {
res.sendFile(path.join(__dirname, "html", req.path + ".html"));
return;
}
next();
});
If you have a lot of static pages, the ideal way would be to put them up in a single route, lets call it static.js. It can be something like,
module.exports = function () {
var router = require('express').Router();
var pages = {
'about-us': 'path/to/about-us',
'contact-us': 'path/to/contact-us'
};
router.get('/:page', function (req, res, next) {
if (! pages[req.params.page]) {
return next();
}
res.render(pages[req.params.page]);
});
return router;
};
Attach this route to the app, app.use(require('./static')()); and you are good to go.
Try this.
app.use(express.static(path.join(__dirname, 'xyz')));
where xyz is the folder you are trying to make available as static. The folder name is relative to the application root.