6

The closest I've been able to get is it will have the client download them. It will download the correct ejs files.

It's driving me crazy because I feel like it should work but it will not. If I put html files in there they serve just fine. It's a little messy because I've been trying all sorts of things.

var application_root = __dirname;
var express = require('express');
var vhost = require( 'vhost' );
var https = require('https');
var http = require('http');
var fs = require('fs');
var path = require("path");
var forceSSL = require('express-force-ssl');
//do something
var app = express();
var credentials = {};

var config = require('./config.json')[process.env.NODE_ENV || 'dev'];

//Use ejs?
app.set('view engine', 'ejs');
app.engine('html', require('ejs').renderFile);

//Ensure all are going to www.
app.all(/.*/, function(req, res, next) {
  var host = req.header("host");
  if (host.match(/^www\..*/i)) {
    next();
  } else {
    res.redirect(301, "http://www." + host);
  }
});

//Use the virtual hosts
app.use(vhost('*.seq.agency',express.static(path.join(__dirname + '/seq.agency'), {
  extensions: ['ejs'],
  index: 'index.ejs'
})));

app.get('/', function (req, res) {
  res.send('vhosts didn\'t catch this!')
});

var httpServer = http.createServer(app);
if(config.name == "prod"){
    /*var options = {
         key: fs.readFileSync('/etc/letsencrypt/live/kaleidoscope.wtf/privkey.pem'),
         cert: fs.readFileSync('/etc/letsencrypt/live/kaleidoscope.wtf/fullchain.pem'),
         ca: fs.readFileSync('/etc/letsencrypt/live/kaleidoscope.wtf/chain.pem')
    }*/
    console.log('starting on 443');
    //var httpsServer = https.createServer(options, app);
    //httpsServer.listen(443);
    //httpServer.listen(80);
    //app.use(forceSSL);
}

console.log('['+config.name+'] starting on port',config.port);
httpServer.listen(config.port);
Z2VvZ3Vp
  • 7,033
  • 6
  • 21
  • 35
  • Are you trying to serve the rendered output of the EJS files? – Patrick Roberts Mar 01 '18 at 22:40
  • Have you tried this instead `app.engine('ejs', require('ejs').renderFile);`? I believe that it's converting it to a .html file before reaching the vhost. – RickyM Mar 01 '18 at 23:03
  • @PatrickRoberts yes I basically just want to use multiple pages that use `<% include('partials/header.ejs'); %>` etc – Z2VvZ3Vp Mar 03 '18 at 05:19
  • @RickyM I just tried that. if i leave the file as .html file it just prints any ejs tags, if i make it an ejs file it isn't caught by the vhosts – Z2VvZ3Vp Mar 03 '18 at 05:20
  • Why are you adding `express.static` for the `ejs` files? – Tarun Lalwani Mar 03 '18 at 05:37
  • @TarunLalwani because I don't want to have to explicitly state all the routes, I want the pages to serve as static pages, so if I add an html file it can be served without changing the server. – Z2VvZ3Vp Mar 03 '18 at 06:00
  • @PixMach, that is the main issue. Please check the answer I have posted – Tarun Lalwani Mar 03 '18 at 10:02

1 Answers1

5

The issue is that you are considering that static files are rendered. Static file as the name suggest is static and there is no dynamic behavior and template rendering needed for the same

That is why below code cannot work

app.use(vhost('*.seq.agency',express.static(path.join(__dirname + '/seq.agency'), {
  extensions: ['ejs'],
  index: 'index.ejs'
})));

As you are asking it to serve files as it is with no processing. So I modified your code a bit to show you an example how you could work something out on this

var application_root = __dirname;
var express = require('express');
var vhost = require( 'vhost' );
var https = require('https');
var http = require('http');
var fs = require('fs');
var path = require("path");
var forceSSL = require('express-force-ssl');
//do something
var app = express();
var credentials = {};

var config = require('./config.json')[process.env.NODE_ENV || 'dev'];

//Use ejs?
ejs = require("ejs");
app.set('view engine', 'html');
app.engine('html', ejs.renderFile);
app.engine('ejs', ejs.renderFile);

//Ensure all are going to www.
app.all(/.*/, function(req, res, next) {
    var host = req.header("host");
    if (host.match(/^www\..*/i)) {
        next();
    } else {
        res.redirect(301, "http://www." + host);
    }
});

//Use the virtual hosts
app.use(vhost('*.seq.agency',function (req, res, next)
{
    const reqPath = req.path;
    const paths =
        [
            reqPath + ".html",
            reqPath + "index.html",
            reqPath
        ]

    for (file of paths) {
        try {
            let checkPath = path.join(__dirname,"seq.agency", file);
            if (!fs.existsSync(checkPath))
                continue;

            let stat = fs.statSync(checkPath);
            if (stat && stat.isFile())
            {
                res.render(checkPath);
                return;
            }
        } finally {

        }
    }

    console.log(file);
}));

app.get('/', function (req, res) {
    res.send('vhosts didn\'t catch this!')
});

var httpServer = http.createServer(app);
if(config.name == "prod"){
    /*var options = {
         key: fs.readFileSync('/etc/letsencrypt/live/kaleidoscope.wtf/privkey.pem'),
         cert: fs.readFileSync('/etc/letsencrypt/live/kaleidoscope.wtf/fullchain.pem'),
         ca: fs.readFileSync('/etc/letsencrypt/live/kaleidoscope.wtf/chain.pem')
    }*/
    console.log('starting on 443');
    //var httpsServer = https.createServer(options, app);
    //httpsServer.listen(443);
    //httpServer.listen(80);
    //app.use(forceSSL);
}

console.log('['+config.name+'] starting on port',config.port);
httpServer.listen(config.port);

So the key is that we check a path in below order

reqPath + ".html",
reqPath + "index.html",
reqPath

And then if it exists then we render that in response. This is no way a production use code as it allows you to directory traversal attack, but this is to give you an idea of what you are doing wrong and how you should handle it

Working

Tarun Lalwani
  • 142,312
  • 9
  • 204
  • 265