如何知道 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
属性(http
或 https
)会更快。但是请注意,对于传出链接,您只需引用//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.secure
是req.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 执行的?
Elastic beanstalk 请求上的 Node.js 是 HTTPS,但 express 是作为 HTTP 服务的。这安全吗?