我一直在尝试用我正在做的一个node.js项目来设置HTTPS。我基本上遵循了这个例子的node.js文档:

// curl -k https://localhost:8000/
var https = require('https');
var fs = require('fs');

var options = {
  key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'),
  cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem')
};

https.createServer(options, function (req, res) {
  res.writeHead(200);
  res.end("hello world\n");
}).listen(8000);

现在,当我做的时候

curl -k https://localhost:8000/

我得到

hello world

像预期的那样。但如果我这样做了

curl -k http://localhost:8000/

我得到

curl: (52) Empty reply from server

回想起来,这似乎是显而易见的,它将以这种方式工作,但与此同时,最终访问我的项目的人不会输入https://yadayada,我希望所有的流量从他们访问网站的那一刻起就使用https。

我怎么能得到节点(和Express,因为这是我正在使用的框架)把所有传入的流量交给https,不管它是否被指定?我还没有找到任何解决这个问题的文档。或者只是假设在生产环境中,节点在它前面有一些东西(例如nginx)来处理这种重定向?

这是我第一次尝试web开发,所以如果这是显而易见的,请原谅我的无知。


当前回答

这个脚本在加载页面时保存URL页面,并检查地址是https还是http。如果是http,脚本会自动将您重定向到相同的https页面

(function(){
  var link = window.location.href;
  if(link[4] != "s"){
    var clink = "";
    for (let i = 4; i < link.length; i++) {
      clink += link[i];
    }
    window.location.href = "https" + clink;
  }
})();

其他回答

你可以实例化2个Node.js服务器——一个用于HTTP,一个用于HTTPS

还可以定义两台服务器都将执行的设置函数,这样就不必编写大量重复的代码。

下面是我的方法:(使用retify .js,但应该适用于express.js,或node本身)

http://qugstart.com/blog/node-js/node-js-restify-server-with-both-http-and-https/

经过多年研究从http到https的完美重定向,我在这里找到了完美的解决方案。

const http = require("http");
const https = require("https");

const { parse } = require("url");
const next = require("next");
const fs = require("fs");

const ports = {
http: 3000,
https: 3001
}

const dev = process.env.NODE_ENV !== "production";
const app = next({ dev });
const handle = app.getRequestHandler();

const httpsOptions = {
key: fs.readFileSync("resources/certificates/localhost-key.pem"),
cert: fs.readFileSync("resources/certificates/localhost.pem")
};

// Automatic HTTPS connection/redirect with node.js/express
// source: https://stackoverflow.com/questions/7450940/automatic-https- 
connection-redirect-with-node-js-express
app.prepare().then(() => {

// Redirect from http port to https
http.createServer(function (req, res) {
    res.writeHead(301, { "Location": "https://" + req.headers['host'].replace(ports.http, ports.https) + req.url });
    console.log("http request, will go to >> ");
    console.log("https://" + req.headers['host'].replace(ports.http, ports.https) + req.url);
    res.end();
}).listen(ports.http, (err) => {
    if (err) throw err;
    console.log("ready - started server on url: http://localhost:" + ports.http);
});

https.createServer(httpsOptions, (req, res) => {
    const parsedUrl = parse(req.url, true);
    handle(req, res, parsedUrl);
}).listen(ports.https, (err) => {
    if (err) throw err;
    console.log("ready - started server on url: https://localhost:" + ports.https);
});
});

你可以使用“net”模块在同一个端口上监听HTTP和HTTPS

var https = require('https');
var http = require('http');
var fs = require('fs');

var net=require('net');
var handle=net.createServer().listen(8000)

var options = {
  key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'),
  cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem')
};

https.createServer(options, function (req, res) {
  res.writeHead(200);
  res.end("hello world\n");
}).listen(handle);

http.createServer(function(req,res){
  res.writeHead(200);
  res.end("hello world\n");
}).listen(handle)

这个想法是检查传入的请求是否使用https,如果是,就不要再次重定向到https,而是像往常一样继续。否则,如果它是http,则通过附加https重定向它。

app.use (function (req, res, next) {
  if (req.secure) {
          next();
  } else {
          res.redirect('https://' + req.headers.host + req.url);
  }
});

这里的大多数答案都建议使用req.headers.host头文件。

Host报头是HTTP 1.1所要求的,但它实际上是可选的,因为报头可能不是由HTTP客户端实际发送的,node/express将接受这个请求。

你可能会问:哪个HTTP客户端(例如:浏览器)可以发送一个缺少报头的请求?HTTP协议非常简单。您可以用几行代码编写一个HTTP请求,以不发送主机标头,如果每次接收到格式错误的请求时都抛出一个异常,根据处理此类异常的方式,这可能会导致服务器宕机。

所以总是验证所有输入。这不是妄想症,我在我的服务中收到过缺少主机头的请求。

另外,永远不要把url当作字符串。使用node url模块修改字符串的特定部分。将url视为字符串可以通过许多许多方式加以利用。不要这样做。