【问题标题】:React Router Paths, SNICallback, POST, GETReact 路由器路径、SNICallback、POST、GET
【发布时间】:2017-10-27 23:07:27
【问题描述】:

我已经构建了以下快速应用程序,以从单个服务器使用 HTTPS 为多个站点提供服务:

// strict
'use strict';

// vars
const tls = require('tls');
var fs = require('fs');
var http = require('http');
var https = require('https');
var express = require('express');
var vhost = require('vhost');
var forceSSL = require('express-force-ssl');
var cors = require('cors');
var app = express();
var server;
var secureServer;

// always force HTTP -> HTTPS redirect
app.use(forceSSL);

// allow cross origin
app.use(cors());

// Express settings (main switch logic - each host, and each static directory)
var siteOne = vhost('siteone.com', express.static('../siteone/dist'));
var wwwSiteOne = vhost('www.siteone.com', express.static('../siteone/dist'));
var siteTwo = vhost('sitetwo.com', express.static('../sitetwo/dist'));
var wwwSiteTwo = vhost('www.sitetwo.com', express.static('../sitetwo/dist'));

app.use(cors()); // allow cross origin
app.use(siteOne); // all hosts defined above
app.use(wwwSiteOne);
app.use(siteTwo);
app.use(wwwSiteTwo);

app.use(function(req, res, next) { // 404 page as last "use" call
  res.status(404).send('404 page :(');
});

// HTTP Server - http.createServer is enough for our HTTP needs
server = http.createServer(app);
server.listen(8080);  // router is set to forward port 80 (http requests) to port 8080

// HTTPS Server - use virtual host to redirect with secureserver
var secureContext = {
    'siteone.com': tls.createSecureContext({
        key: fs.readFileSync('../../sslcert/siteone/privkey.pem', 'utf8'),
        cert: fs.readFileSync('../../sslcert/siteone/fullchain.pem', 'utf8'),
        ca: fs.readFileSync('../../sslcert/siteone/chain.pem', 'utf8'),
    }),
    'www.siteone.com': tls.createSecureContext({
        key: fs.readFileSync('../../sslcert/siteone/privkey.pem', 'utf8'),
        cert: fs.readFileSync('../../sslcert/siteone/fullchain.pem', 'utf8'),
        ca: fs.readFileSync('../../sslcert/siteone/chain.pem', 'utf8'),
    }),
    'sitetwo.com': tls.createSecureContext({
                key: fs.readFileSync('../../sslcert/sitetwo/privkey.pem', 'utf8'),
                cert: fs.readFileSync('../../sslcert/sitetwo/fullchain.pem', 'utf8'),
                ca: fs.readFileSync('../../sslcert/sitetwo/chain.pem', 'utf8'),
    }),
    'www.sitetwo.com': tls.createSecureContext({
                key: fs.readFileSync('../../sslcert/sitetwo/privkey.pem', 'utf8'),
                cert: fs.readFileSync('../../sslcert/sitetwo/fullchain.pem', 'utf8'),
                ca: fs.readFileSync('../../sslcert/sitetwo/chain.pem', 'utf8'),
    }),
}
try {
    var options = {
        SNICallback: function (domain, cb) {
            if (secureContext[domain]) {
                if (cb) {
                    cb(null, secureContext[domain]);
                } else {
                    // compatibility for older versions of node
                    return secureContext[domain];
                }
            } else {
                console.log('Doing nothing. Domain requsted: ' + domain);
            }
        },
       // must list a default key and cert because required by tls.createServer()
        key: fs.readFileSync('../../sslcert/siteone/privkey.pem'),
        cert: fs.readFileSync('../../sslcert/siteone/fullchain.pem'),
    }
    secureServer = https.createServer(options, app);
        secureServer.listen(8043);  // router is set to forward port 443 (https requests) to port 8043
} catch (err){
    console.error(err.message);
    console.error(err.stack);
}

到目前为止,我遇到了 POST、GET 和 react 路由器 (v4) 路径的问题。例如,带有反应路由器的单页站点只要用户从主页开始,但如果用户直接在 url 栏中提供链接(例如 siteone.com /somecoolpath) 我从网站切换获得 404 页面。

类似地,我有一个来自网站的 POST,用于将用户的电子邮件添加到位于 url 路径 /add_email 上的数据库中......当我发送电子邮件时,我总是收到 404......

所有这些路径都适用于它们自己的应用程序,但当我通过此 SNICallback 开关提供服务时则不行。

我尝试过但没有用的方法:

虚拟主机中的通配符:

var reactRouterSite = vhost('siteone.com*', express.static('../siteone/dist'));

在 SNI 回调中重写域:

SNICallback: function (domain, cb) {
    if (domain.includes('siteone')) { // any request from siteone
        domain = 'siteone.com'
    }
    ...

最后一个 app.use() 语句中的最后一个 switch() 语句:

app.use(function(req, res, next) { 
    console.log(req);
    switch (req.url) {
      case '/somecoolpath':
        return siteOne;
        break;
      default:
        res.status(404).send('404 page :(');
    }
});

我已经花了几个小时寻找可能的解决方案,但甚至没有找到一个带有 SNICallback 的反应路由器的案例示例......我可以尝试什么想法?还是有更简单的解决方案?

所有站点都托管在其他节点实例中,端口 8081、8082 等上的快速应用程序。对于所有站点,根页面通过此“开关”按预期加载,只是那些 GET/POST url 和复制/粘贴不起作用的路由器网址。

【问题讨论】:

    标签: node.js express react-router-v4


    【解决方案1】:

    您可以做的一件事是摆脱 vhosts 中间件,只需创建一个app.get('*') 路由并自己执行逻辑检查req.hostname,而不是使用静态目录,而是渲染一个模板。我已经使用多个域和多个 React 应用程序完成了此操作。

    【讨论】:

      【解决方案2】:

      根据 dzm 的回复,我最终确实取出了 vhost 中间件,而是使用了 app.get('*' ...) 路由,但我没有渲染模板,而是发现代理最适合我的需求,并使用了 @ 987654321@。经过一些测试,可以直接在浏览器中复制/粘贴react路由器路径并按预期工作,GET/POST方法也可以工作,只要app.get()app.post()路径也存在于网站开关中.

      替换vhosts / app.use() 部分,同时保留代码的其他部分,即SNICallbacksecureContext,解决方案如下所示:

      // set up proxy server
      var httpProxy = require('http-proxy');
      var proxy = httpProxy.createProxyServer({}); // leave options empty --> custom logic below in app.get('*' ...)
      
      // GET paths
      app.get('*', function(req, res) {
        // custom logic to handle and proxy the request
        console.log(req.hostname);
        switch (req.hostname) {
          case 'siteone.com':
            proxy.web(req, res, { target: 'http://127.0.0.1:8081' }); // different node server running on local port 8081
            break;
          case 'sitetwo.com':
            proxy.web(req, res, { target: 'http://127.0.0.1:8082' }); // different node server running on local port 8082
            break;
          default:
            res.status(404).send('404 page :(');
            break;
        }
      });
      
      // POST paths (for siteone)
      app.post('/new_email', function(req, res) {
        proxy.web(req, res, { target: 'http://127.0.0.1:8081' }); // this post path must also be written on the index.js of siteone.com
      });
      

      【讨论】:

        猜你喜欢
        • 2020-07-27
        • 1970-01-01
        • 2017-08-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-08
        • 2017-10-21
        • 2021-08-03
        相关资源
        最近更新 更多