如何知道 node.js 中的请求是 http 还是 https

Posted

技术标签:

【中文标题】如何知道 node.js 中的请求是 http 还是 https【英文标题】:How to know if a request is http or https in node.js 【发布时间】:2012-05-08 02:23:48 【问题描述】:

我正在使用 nodejs 和 expressjs。我想知道 clientRequest 对象中是否有类似request.headers.protocol 的东西。我想为 Web 链接构建 baseUrl。因此,如果请求是通过 https 完成的,我想在所有链接中保留 https。

    var baseUrl = request.headers.protocol + request.headers.host;

【问题讨论】:

【参考方案1】:

编辑: 对于 Express,它更安全,建议使用 req.secure(如下面的 @Andy 建议)。虽然它使用类似的实现,但它对将来的使用是安全的,并且它还可以选择支持 X-Forwarded-Proto 标头。

话虽如此,对于您的用例,使用 Express 的 req.protocol 属性(httphttps)会更快。但是请注意,对于传出链接,您只需引用//example.com/path,浏览器将使用当前协议。 (另见Can I change all my http:// links to just //?)

对于没有 Express 的节点 Request 对象:

req.connection.secure(布尔值)中。

编辑: 对于 Node 0.6.15+,API 已更改:

HTTPS 连接具有req.connection.encrypted(包含有关 SSL 连接信息的对象)。 HTTP 连接没有req.connection.encrypted

另外(来自the docs):

使用 HTTPS 支持,使用 request.connection.verifyPeer() 和 request.connection.getPeerCertificate() 获取客户端的身份验证详细信息。

【讨论】:

在最新的节点 0.10 及更高版本中是否仍然可用? 嗯,您能否为以后的节点版本(如 0.8 及更高版本)验证这一点,我在文档中找不到任何此类内容。但可能是我读错地方了。 至少when using express,可以依赖req.secure(作为布尔属性)或同样的'https' == req.protocol 我正在运行 NodeJs v11.5.0 并且请求对象不包含 .connection.encrypted -- 我现在怎么知道? 试试req.socket.encrypted。在最新版本的 Node.js 中,.connection 属性已更改为 .socket 属性。 nodejs.org/dist/latest-v12.x/docs/api/…【参考方案2】:

req.securereq.protocol === 'https' 的简写,应该是你要找的。​​p>

如果您在代理后面运行您的应用,请启用“信任代理”,以便 req.protocol 反映用于在客户端和代理之间进行通信的协议。

app.enable('trust proxy');

【讨论】:

哦,对,和require('url').parse(..).protocol混淆了 很高兴提及app.enable('trust proxy'); 不使用它会导致重定向循环。 @Ben node v5.x 和这个有什么关系?请阅读 express 4.x 的文档(这是迄今为止最新的):expressjs.com/en/4x/api.html#req.protocol【参考方案3】:

你不需要在 URL 中指定协议,因此你不需要为这个问题而烦恼。

如果您使用<img src="//mysite.comm/images/image.jpg" />,如果页面以 HTTP 提供,浏览器将使用 HTTP,如果页面以 HTTPS 提供,则浏览器将使用 HTTPS。在另一个线程中查看the @Jukka K. Korpela explanation。

【讨论】:

谢谢 Gerardo,你是对的,但是对于这个项目,我需要检测协议。 但这不适用于通用应用程序,在服务器上您必须指定协议【参考方案4】:

对于纯 NodeJS(这在本地工作和部署,例如在 nginx 后面):

function getProtocol (req) 
    var proto = req.connection.encrypted ? 'https' : 'http';
    // only do this if you trust the proxy
    proto = req.headers['x-forwarded-proto'] || proto;
    return proto.split(/\s*,\s*/)[0];

【讨论】:

【参考方案5】:

如果您想知道请求是 http 还是 https,请在您的代码中使用:

req.headers.referer.split(':')[0];

这将返回 req 是 http 还是 https。

【讨论】:

它只在用户从同一个站点重定向时有效,当使用直接在浏览器导航栏中输入域访问该站点时,它不起作用【参考方案6】:

这对我有用:

req.headers['x-forwarded-proto']

希望这有帮助,

E

【讨论】:

请注意,这仅在您的应用程序在设置此标头的反向代理后面运行时才有效 - 这是一个好主意,但可能并非如此,尤其是在例如本地开发环境。 (另外,请记住,如果您在代理后面,客户端可能会欺骗标头,因此请小心您如何信任它。) 另外,在某些情况下,这会为您提供 ip 而不是 http 主机! 我正在使用 OpenShift,这是该服务的正确答案(req.secure 和 req.protocol 不起作用);只是想我会提一下,以防其他人也是。【参考方案7】:

这对我有用:

getAPIHostAndPort = function(req, appendEndSlash) 
    return (req.connection && req.connection.encrypted ? 'https' : 'http') + '://' + req.headers.host + (appendEndSlash ? '/' : '');

【讨论】:

【参考方案8】:

如果您正在使用请求模块,例如想知道某些 www 使用什么协议,您可以使用:response.request.uri.protocol

request(YOUR_TARGET, function(error, response, body)
    if (error)
        console.log(error);
    
    else 
        console.log(response.request.uri.protocol); // will show HTTP or HTTPS
    
);

如果您需要用户协议,请使用 request.headers.referer.split(':')[0]; 就像 @Harsh 给你的那样。

【讨论】:

【参考方案9】:

如果您使用的是 Nginx 等代理服务器,您应该在其配置文件中设置 proxy_set_header X-Forwarded-Proto https;,因此如果您使用的是 TSL,express 可以将 https 识别为 req.headers['x-forwarded-proto'] 值或将 true 识别为 req.secure

【讨论】:

【参考方案10】:

如果要查找请求协议字符串:http 或(对于 TLS 请求)https 只需使用

 req.protocol

快递文档:https://expressjs.com/en/4x/api.html#req.protocol

【讨论】:

以上是关于如何知道 node.js 中的请求是 http 还是 https的主要内容,如果未能解决你的问题,请参考以下文章

我如何知道对 servlet 的请求是使用 HTTP 还是 HTTPS 执行的?

Linux中的请求是如何通过nginx转发到tomcat

Elastic beanstalk 请求上的 Node.js 是 HTTPS,但 express 是作为 HTTP 服务的。这安全吗?

Node.js如何将数组索引传递给异步函数

Node.js作web服务器总结

如何使用 Node.js 通过代理发送 HTTP/2 请求?