Hapijs using both Http and Https on one connection

▼魔方 西西 提交于 2019-12-04 15:37:41

问题


New to Hapijs and trying to use it to create an app that uses HTTPS for all requests and redirect HTTP to the secure connection.The problem is the app goes in HTTPS mode no problem but if i change the URL to HTTP the server does not respond and don't know the reason why.

This is what i have came up with so far, it works but not for HTTP

var connectionOptions = {
    port: 3000,
    tls: {
        key: fs.readFileSync(path.join(__dirname, 'key/key.pem'), 'utf8'),
        cert: fs.readFileSync(path.join(__dirname, 'key/cert.pem'), 'utf8')
    }
};

var server = new Hapi.Server();
server.connection(connectionOptions);

//This method not called when its HTTP
server.ext('onRequest', function (request, reply) {
     if (request.headers['x-forwarded-proto'] === 'http') {
            reply.redirect('https://' + request.headers.host +
                            request.url.path).code(301);
            return reply.continue();
      }
      reply.continue();       
});

var routes = require('./routes')(server);
server.route(routes);

if (!module.parent) {
    server.start(function () {
         console.log('Server running at:', server.info.uri);
    });
 }

How to force all request to be HTTPS. Thank you for the help


回答1:


You can't use http and https on the same connection. Behind the scenes Hapi will create a Node http server or an https server depending on your tls config, as shown in this line from lib/connection.js:

this.listener = this.settings.listener || (this.settings.tls ? Https.createServer(this.settings.tls) : Http.createServer());

You should create another connection to your server that doesn't use TLS and then redirect non-TLS requests to the https url.

EXAMPLE

const Hapi = require('hapi');
const Fs = require('fs');
const Url = require('url');

const config = {
    host: 'localhost',
    http: { port: 3001 },
    https: {
        port: 3000,
        key: Fs.readFileSync('key.key'),
        cert: Fs.readFileSync('cert.pem')
    }
}

const server = new Hapi.Server();

// https connection

server.connection({
    port: config.https.port,
    tls: {
        key: config.https.key,
        cert: config.https.cert
    }
});

// http connection

server.connection({ port: config.http.port });

server.route({
    method: 'GET',
    path: '/',
    handler: function (request, reply) {

        reply('Hello world');
    }
});

server.ext('onRequest', (request, reply) => {

    if (request.connection.info.port !== config.https.port) {

        return reply.redirect(Url.format({
            protocol: 'https',
            hostname: request.info.hostname,
            pathname: request.url.path,
            port: config.https.port
        }));
    }

    return reply.continue();
});

server.start((err) => {

    if (err) {
        throw err;
    }

    console.log('Started server');
});

EDIT

If you're allowing insecure connections to your server before redirecting to HTTPS, consider also employing HTTP Strict Transport Security (HSTS) to prevent MITM attacks. You can set HSTS headers using the route config security option:

server.route({
    config: {
        security: {
            hsts: {
                maxAge: 15768000,
                includeSubDomains: true,
                preload: true
            }
        }
    },
    method: 'GET',
    path: '/',
    handler: function (request, reply) {

        ...
    }
});



回答2:


Another solution that justs reroutes every http call, no checks on every request. You must use 2 connections though.

// create the 2 connections and give the http one a specific label e.g. http
// apply the http catch all route to only the http connection
// I make use of connection label to make sure I only register the catch all route on the http connection
server.select('http').route({
    method: '*',
    path: '/{p*}',
    handler: function (request, reply) {

        // redirect all http traffic to https
        // credit to Matt for the URL.format
        return reply.redirect(Url.format({
            protocol: 'https',
            hostname: request.info.hostname,
            pathname: request.url.path,
            port: config.https.port
        })).permanent();
    },
    config: {
        description: 'Http catch route. Will redirect every http call to https'
    }
});

For more info on the redirect see the docs



来源:https://stackoverflow.com/questions/28650829/hapijs-using-both-http-and-https-on-one-connection

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