【问题标题】:Node.js www - non www redirectionNode.js www - 非 www 重定向
【发布时间】:2011-08-10 15:08:14
【问题描述】:

是否有机会以某种方式将 www 重定向到 node.js 中的非 www URL?由于节点 Web 服务器中没有 htaccess,我很好奇如何做到这一点。

【问题讨论】:

    标签: node.js express


    【解决方案1】:

    尽管这个问题已经有将近 3 年的历史了,但之前发布的答案(和他们的 cmets)存在一些微妙的问题,以及 cmets 中的一些很好的建议,但它们本身并没有回到答案中.以下是一些需要注意的重要事项:

    1. 不要在重定向 URI 中硬编码 http:// 或 https://;在开发环境和生产环境之间切换时,这会让生活变得很糟糕 - 请改用 req.protocol。
    2. 另请注意,为了在执行 SSL 终止的代理(例如 Elastic Load Balancer)后可靠地使用 req.protocol,您需要确保启用了 trust proxy 设置。这将确保 req.protocol 返回浏览器看到的协议,而不是最终到达您的应用服务器的协议。
    3. 接受的答案有一个逻辑错误,因为它与/^www/ 匹配,但使用/^www./ 格式化重定向URI。实际上,这可能不会咬人,但它会导致wwwgotcha.example.com之类的无限重定向循环。
    4. 请务必使用req.headers.host 而不是req.host,因为后者会去掉端口号。因此,如果您要处理对 www.example.com:3000 的请求,您需要将用户重定向到 www.example.com,减去正确的端口号。
    5. 作为Dário pointed out,您通常希望在从 www 转到非 www(反之亦然)时使用 301 重定向以实现 SEO 目的。
    6. 最后一个问题是最次要的,但在创建重定向 URI 时使用 req.originalUrl 通常更安全,以防万一您碰巧在已挂载的“子应用程序”中运行。

    综上所述,这是我推荐的方法,考虑到上述情况:

    function wwwRedirect(req, res, next) {
        if (req.headers.host.slice(0, 4) === 'www.') {
            var newHost = req.headers.host.slice(4);
            return res.redirect(301, req.protocol + '://' + newHost + req.originalUrl);
        }
        next();
    };
    
    app.set('trust proxy', true);
    app.use(wwwRedirect);
    

    【讨论】:

    • 感谢您的深入回答。我的问题是,节点是进行此类重定向的地方吗?我知道 nginx 或 Apache 通常应该处理这些事情,但我无法摆脱 node 真的不应该的感觉。有没有办法在 DNS 级别进行设置?
    • @JamesSpence 好问题。您不会(不能)在 DNS 级别执行 HTTP(S) 和/或 www 重定向,但 nginx 无疑是适合这项工作的工具。 Nginx 在各种攻击缓解方面也是一个有价值的工具,所以坦率地说,没有它我不会离开家。话虽如此,在节点领域这样做也没有根本性的错误,特别是如果您不想在混合中引入新的反向代理,否则将无济于事。
    • 您的答案非常有用,应该是公认的答案。开箱即用!
    【解决方案2】:

    您使用的是快递,对吗?如果是这样,您可以创建一个所有 GET 请求都通过的路由处理程序,检查它们是否指向“www”URL,并在适当时重定向到适当的非 www URL。

    app.get('/*', function(req, res, next) {
      if (req.headers.host.match(/^www/) !== null ) {
        res.redirect('http://' + req.headers.host.replace(/^www\./, '') + req.url);
      } else {
        next();     
      }
    })
    

    【讨论】:

    • 您可以将get 替换为all ;)
    • 并在之前检查req.headers 是否存在! ;)
    • 另外,请确保将 301 设置为重定向的第一个参数(默认情况下,Express 重定向为 302)
    • 你可以只使用 req.host:expressjs.com/api.html#req.host 我也建议使用 req.protocol + '://' 而不是硬编码 http://
    • 好的,最后一条评论 - 我试图在一个新答案中总结各种陷阱(抱歉评论垃圾邮件!):stackoverflow.com/a/23816083/376789
    【解决方案3】:

    jmar777的回答的更新版本:

    使用快递

    server.use((req, res, next) => {
      if (req.headers.host.startsWith('www.')) {
          const newHost = req.headers.host.slice(4)
          return res.redirect(
            301,
            `${req.protocol}://${newHost}${req.originalUrl}`,
          )
      }
      next()
    })
    

    【讨论】:

      【解决方案4】:

      这是一个基本示例,说明如何在 nodejs 中模仿 apache 的重定向指令的行为。

      函数重定向接受正则表达式或字符串。

      var http, redirect;
      http = require("http");
      redirect = function(host, res, pattern, redirect){
          if (host == pattern || (pattern instanceof RegExp && host.match(pattern))) {
              console.log("Redirected " + host);
              res.writeHead(302, {
              'location': redirect
          });
          res.end();
      }};
      
      http.createServer(function(req, res){
          redirect(req.headers.host, res, /^www/, 'http://plouf.url');
          redirect(req.headers.host, res, 'www.plouf.url', 'http://plouf.url');
          res.writeHead(200, {
              'Content-Type': 'text/plain'
          });
          res.end('Hello World\n');
      }).listen(8000, '127.0.0.1');
      

      【讨论】:

      【解决方案5】:

      在 DevOps 和越来越多地采用托管平台的世界中,这类事情永远不应该由代码来处理。您应该改用基础设施来处理重定向。将此代码放入应用程序意味着如果顶点条目中出现问题,运营团队将无法缓解问题。此外,虽然它花哨、闪亮和时髦,但使用顶点作为您的站点 url 会限制操作在出现问题时重定向站点的能力,并在您想要进行蓝/绿、A/B 测试或地理重定向(在某些情况下)。您的代码和应用程​​序应该与 url 无关。

      【讨论】:

        【解决方案6】:

        如果您使用的是 Express,我同意上述 Sebastian 的观点,但需要稍作调整。我只是将它作为一个中间件,它将在所有请求上进行处理。

        function removeWWW(req, res, next){
            if (req.headers.host.match(/^www/) !== null ) {
                res.redirect('http://' + req.headers.host.replace(/^www\./, '') + req.url);
            } else {
                next();     
            } 
        }
        app.use(removeWWW);
        

        【讨论】:

          猜你喜欢
          • 2019-01-29
          • 2011-04-12
          • 2012-06-03
          • 2018-06-06
          • 2015-12-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多