2015-02-21 3 views
3

Новое в Hapijs и пытается использовать его для создания приложения, которое использует HTTPS для всех запросов и перенаправляет HTTP на безопасное соединение. Проблема заключается в том, что приложение не работает в режиме HTTPS, но проблема не возникает если я изменяю URL-адрес HTTP, сервер не отвечает и не знает причину.Hapijs с использованием Http и Https на одном соединении

Это то, что я придумал до сих пор, он работает, но не для 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); 
    }); 
} 

Как заставить все просьбы быть HTTPS. Благодарим за помощь

ответ

12

Вы не можете использовать http и https в том же соединении. За кулисами Hapi будет создать узел http сервер илиhttps сервера в зависимости от вашего tls конфигурации, как показано на этой линии от lib/connection.js:

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

Вы должны создать другое соединение с сервером, который Безразлично» t использовать TLS, а затем перенаправить запросы без TLS на https-url.

Пример

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

Если вы позволяете небезопасные соединения с сервером перед перенаправлением в HTTPS, рассмотрим также с использованием HTTP Strict Transport Security (HSTS) для предотвращения MITM атак. Вы можете установить заголовки HSTS с использованием маршрутом CONFIG security варианта:

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

     ... 
    } 
}); 
+0

Фигурных что много, спасибо, но есть несколько примеров, показывая хорошую практику в его настройке или это плохая идея, и лучше использовать одно подключение HTTP-ам , заставляют думать о развертывании его в Heroku и не знаю, как работать с двумя серверами в одном приложении. Большое спасибо за помощь. – ramon22

+0

@ ramon22 Я добавил пример ответа. Я не слишком уверен в отношении Heroku, поскольку я никогда не использовал его, но вы, вероятно, правы, я полагаю, что они сами позаботятся о завершении SSL и всегда проксируют HTTP-трафик. В этом случае вы действительно захотите проверить заголовок 'x-forwarded-proto' и перенаправить на основе значения этого. –

5

Другим решением, которое Justs перенаправляет каждый HTTP вызов, не проверяет на каждом запросе. Вы должны использовать только 2 соединения.

// 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' 
    } 
}); 

Для получения дополнительной информации о перенаправлении см the docs

+0

Какие-либо тесты, указывающие на вышеупомянутый ответ, не являются результативными? Это только сравнение двух чисел, которые уже находятся в памяти, которые, я думаю, очень и очень дешевы. –

+0

Моя формулировка, вероятно, немного выключена. Простите за это. Основное различие между нашими решениями заключается в том, что ваше решение проверяет каждый запрос, пока мой будет перенаправлять только каждый HTTP-вызов, без проверки и только на http-запросы. Ваша реальная переадресация выглядит лучше. Позвольте мне уточнить свой ответ. –

Смежные вопросы