Force SSL on App Engine Flexible Environment Custom Runtime

不羁岁月 提交于 2019-11-27 09:06:43

App Engine Flex doesn't support handlers, at all: https://cloud.google.com/appengine/docs/flexible/java/upgrading#appyaml_changes

If you need https:// redirects, you need to do it from within your application. Sorry!

Since your app (env: flex in app.yaml) is running behind an nginx reverse proxy which terminates the SSL connection, you need to check the X-FORWARDED-PROTO header which will be either http or https. If it’s http then you can do the redirect.

This is what worked for me. In my case using Loopback based NodeJS application running in Cloud Sites App Engine flexible environment.

  1. Create a middleware, for example server/middleware/https-redirect.js with the following code:

    /**
    * Create a middleware to redirect http requests to https
    * @param {Object} options Options
    * @returns {Function} The express middleware handler
    */
    module.exports = function(options) {
      options = options || {};
      var httpsPort = options.httpsPort || 443;
      return function(req, res, next) {
        if (req.protocol != 'https' && process.env.NODE_ENV !== 'development') {
          var parts = req.get('host').split(':');
          var host = parts[0] || '127.0.0.1';
          return res.redirect('https://' + host + ':' + httpsPort + req.url);
        }
        next();
      };
    };
    

    (based on the step 8 in the post http://www.jonxie.com/blog/2014/11/12/setting-up-loopback-to-use-https-and-ssl-certificates/ but modified to use req.protocol instead of req.secure, also will only redirect if not running in development mode)

  2. Modify the file server/server.js to request:

    var httpsRedirect = require('./middleware/https-redirect');
    
  3. An then, after the boot line:

    var httpsPort = app.get('https-port');
    app.use(httpsRedirect({httpsPort: httpsPort}));
    app.set('trust proxy', true)
    

Setting app.set('trust proxy', true) will let the req.protocol read the X-Forwarded-Proto header.

References:

Late to answer, but I had to struggle a lot in order to do this.

I followed various links which mentioned the following code,

app.use(function(req, res, next) {
  if(!req.secure) {
    return res.redirect(['https://', req.get('Host'), req.url].join(''));
  }
  next();
});

This might work in other cloud vendors.

But in GCP as rightly mentioned by @zengabor, our app will be running behind an nginx reverse proxy which terminates the SSL connection, we need to check the X-FORWARDED-PROTO which can be done by the following code,

app.use(function(req, res, next) {
  if(req.headers['x-forwarded-proto'] && req.headers['x-forwarded-proto'] === "http") {
    return res.redirect(['https://', req.get('Host'), req.url].join(''));
  }
  next();
});

Just adding my answer as after reading @zengabor's code I had to search again on how to achieve it. So above is the readymade code which will work.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!