Express获取正确的请求协议

背景

有一个node项目,由于某seo的原因,需要把某些http请求重定向到https

过程

需求很简单,开搞~
因为node是express框架的,这种操作理所应该在中间件中做, 在我们的入口文件中添加:

var protocolRedirect = function (req, res, next) {
  const { protocol, header,  originalUrl} = req;
  // 如果是线上环境,并且是http协议的话就跳走
  if (isOnline && protocol==='http') {
    res.redirect(`https://${headers.host}${originalUrl}`);
  }
  next()
};
app.use(protocolRedirect);

Nice,本地调试,没有问题~ 部署到沙箱环境。
这里说一下我们的沙箱环境有一层nginx转发,支持https以及http协议进行接口请求。

部署完毕,check一下~ 本地用switch host配置下域名ip的映射关系,访问服务对应的页面 http://域名.com/home ,发现控制台不停的发302重定向请求。就很奇怪,,明明代码里会让他重定向到https,之后就不会重定向了啊,查了查服务器日志req.protocol确实是获取到了请求的协议时http

满篇302

难道是重定向https那里有问题了么?直接用浏览器访问https://域名.com/home试了一下 ,居然日志显示此时req.protocol还是http。。。

这可就不对了啊!!明明请求的是https啊!!
if (isOnline && protocol==='http')   // 确实这里有问题

解决

打开google,一顿搜索,发现这种在(nginx)转发代理后的服务需要激活trust proxy,这样才能使我们的服务对后面的代理进行信任从而拿到经过nginx修改过的protocol等信息。


图片来源 stackoverflow

结合下实际情况,我们的沙箱有一层nginx,当https请求对应的域名解析到沙箱nginx之后,nginx会将请求的X-Forwarded-Proto进行修改(改为https),相应的影响我们取req.protocol。以下是我们nginx部分配置。

 location / {
        ...
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $xff;
        proxy_set_header X-Real-IP $remote_address;
        //  $scheme就是请求的协议,是nginx的全局变量
        proxy_set_header X-Forwarded-Proto $scheme;  
        proxy_set_header X-Scheme $scheme; 
        proxy_set_header X-Remote-Port $remote_port;
        ...
 }

在未信任时(即未激活trust proxy时)我们node服务不会接受来路不明的数据,所以req.protocol取出的值仍然是http;

放上最终代码:

var protocolRedirect = function (req, res, next) {
  const { headers, originalUrl } = req;
  if (!isOnline || (isOnline && req.secure)) {
    next();
  } else {
    res.redirect(301, `https://${headers.host}${originalUrl}`);
  }
};
app.enable('trust proxy');
app.use(protocolRedirect);

你可能感兴趣的:(Express获取正确的请求协议)