Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating an Express JS 4.0 application with https on Openshift, including http redirection

Following another SO question, the latest I have been trying is (see ligatures.net):

self.ipaddress = process.env.OPENSHIFT_NODEJS_IP;
self.port      = process.env.OPENSHIFT_NODEJS_PORT || 443;

if (typeof self.ipaddress === "undefined") {
    self.ipaddress = "127.0.0.1";
};

...
self.app = express();  // 4.8.7

...
// Trusting Openshift proxy
self.app.enable('trust proxy');

// Http -> Https redirection middleware
self.app.use(function (req, res, next) {

    if ( !req.secure() ) {
        var tmp = 'https://' + process.env["DOMAIN_NAME"] + req.originalUrl;
        console.log("Redirect to: " + tmp);
        res.redirect(tmp);
    } else {
        next();
    }               

});

...

// Creating a http server
https.createServer(self.app).listen(self.port, self.ipaddress,
    function(err) {
        if (err) {
            console.log("Node server error: " + err.toString());
        } else {
            console.log('%s: Node server started on %s:%d ...',
                Date(Date.now() ), self.ipaddress, self.port);
        }
});

In the Openshift logs, I get:

Property 'secure' of object # is not a function

This is the line: if ( !req.secure() ) {

The certificates are loaded in the console. The application starts successfully on port 8080.

Why am I getting this message and how should I create a secured Express 4.0 https application in OpenShift? Does anyone have operational code to share? Thanks!

UPDATE

I have updated the redirection as following:

// Http -> Https redirection middleware
self.app.use(function (req, res, next) {

    if ( req.headers['x-forwarded-proto'] === 'http' ) { 

        var tmp = 'https://' + req.headers.host + req.originalUrl;
        console.log("SERVER redirect to: " + tmp);
        res.redirect(tmp);

    } else {

        var pt = req.protocol || "";
        var ho = req.headers.host || "";
        var ur = req.originalUrl || "";

        console.log("\nProtocol: " + pt
                  + "\nHost   : " + ho
                  + "\nUrl    : " + ur);

        var tmp = req.protocol + '://' + req.headers.host + req.originalUrl;
        console.log("SERVER no redirect: " + tmp);
        next();

    }

I see a couple of the following from the console:

SERVER no redirect: http://undefined/
Protocol: http
Host   :
Url    : /

and my application still does not work. It looks like a bug to me.

I have opened an issue: https://bugzilla.redhat.com/show_bug.cgi?id=1138137

I am also behind Cloudflare, which may be part of the issue.

like image 872
Jérôme Verstrynge Avatar asked Sep 03 '14 22:09

Jérôme Verstrynge


1 Answers

There were two issues:

i) If you are on Cloudflare's free plan, then it won't forward the SSL requests. If you disactivate Cloudflare (while keeping their DNS for example), then the SSL requests are forwarded to Openshift.

ii) For some unknown reason, some empty requests reach my application on Openshift when starting it, and when browsing pages later too:

req.path: /
req.protocol: http
req.originalUrl: /
req.secure: false

The code mentioned in Openshift's KB article cannot work well as is, for two reasons. First, req.path does not take query parameters into account. One should use req.originalUrl instead in Express 4.0.

Second instead of using self.app.get(r, redirectSec, self.routes[r]);, one should add the middleware with self.app.use in Express 4.0:

My HTTP to HTTPS forwarding code is now:

// Trusting Openshift proxy
self.app.enable('trust proxy');

// Http -> Https redirection middleware
self.app.use(function (req, res, next) {

        if ( req.headers['x-forwarded-proto'] === 'http' ) { 

            var tmp = 'https://' + req.headers.host + req.originalUrl;
            res.redirect(tmp);

        } else {

            return next();

        }

    }

});

All seems to work fine now.

like image 94
Jérôme Verstrynge Avatar answered Sep 28 '22 07:09

Jérôme Verstrynge