Heroku + Node.js + HTTPS
昨天把 biz-to-me 升级到支持 HTTPS 了,为此研究了一下如何让 Heroku 上跑的 Node.js 应用支持 HTTPS。我发现并没有任何文章描述这个具体的流程,只有零碎的信息,所以在此记录一下。
首先,Heroku 应用要支持 HTTPS 必须要是付费的等级,最便宜的是每月 $7 的 Hobby 级别。把应用升级到 Hobby 级别后,我们在应用设置里面添加的域名就能自动获得 SSL 证书,这个过程是全自动的,无需手动操作。(全自动不意味着实时,每次添加新域名都需要等一段时间才会看到「ACM Status」这一栏变成「Ok」的状态。背后实际使用的证书签发机构其实是 Let’s Encrypt。)

一般 Heroku 应用的「DNS Target」是 app-name.herokuapp.com,需要留意的是一旦升级到支持 SSL 后这一栏的内容会改变,变成 app.example.com.herokudns.com,也就是在 herokudns.com 之前加上应用的整个域名。如果之前 DNS 的 CNAME 指向还是 herokuapp.com,那必须记得更新为 herokudns.com,否则 herokuapp.com 不会使用正确的 SSL 证书提供服务。(herokuapp.com 永远只会用 *.herokuapp.com 的证书提供服务,而 herokudns.com 会根据前缀选择正确的证书。)
在大多数情况下,Heroku 应用升级到支持 HTTPS 后应用代码不需要更新,这是因为 SSL 连接在 Heroku 的负载均衡器那里就种终止了,负载均衡器用明文 HTTP 跟应用连接所以应用本身不需要具备处理 HTTPS 的能力。(Node.js 有 https 模块,但调用时需要访问证书私钥,所以还是用 http 模块比较方便。)如果需要在 Node.js 中判断上游请求是不是 HTTPS,可以通过读取 X-Forwarded-Proto header 来实现,这个 header 的取值可以是 "http" 或 "https",例如说在 biz-to-me 中我就通过这一行代码来进行判断。
最后简述一下如何验证配置是否成功。最简单的方法自然是测试一下 HTTPS 服务是否正常工作。biz-to-me 的服务很简单,如果我打开一个 http(s)://*.catchen.biz/* 的 URL,它返回 301 把我重定向到 http(s)://*.catchen.me/*。这篇文章的 URL 是 https://chinese.catchen.me/2018/07/heroku-nodejs-https.html,如果我 curl -i 对应的 catchen.biz URL 能得到正确的 301 重定向那就是成功了。
$ curl -i https://chinese.catchen.biz/2018/07/heroku-nodejs-https.html
HTTP/1.1 301 Moved Permanently
Server: Cowboy
Connection: keep-alive
Location: https://chinese.catchen.me/2018/07/heroku-nodejs-https.html
Date: Sun, 01 Jul 2018 21:29:36 GMT
Transfer-Encoding: chunked
Via: 1.1 vegur
Permanently moved to <a href="https://chinese.catchen.me/2018/07/heroku-nodejs-https.html">https://chinese.catchen.me/2018/07/heroku-nodejs-https.html</a>.
留意 Location header 的值是 HTTPS 开头的而非 HTTP,因为在 Node.js 代码更新到支持 HTTPS 之前我们也能得到类似的 301 响应,只不过 Location 永远都只是 HTTP 的。
如果 curl -i 因为证书不正确而出错的话,可以用 curl --insecure 来忽略证书验证 Node.js 代码。然后再用 curl -v 来查看证书,看看到底为什么证书错误。curl -v 的结果关键看这一段:
* Server certificate:
* subject: CN=cantonese.catchen.biz
* start date: Jul 1 04:44:37 2018 GMT
* expire date: Sep 29 04:44:37 2018 GMT
* subjectAltName: host "chinese.catchen.biz" matched cert's "chinese.catchen.biz"
* issuer: C=US; O=Let's Encrypt; CN=Let's Encrypt Authority X3
* SSL certificate verify ok.
如果 Heroku 应用只添加了一个域名,subject 那一行的域名必须是这个唯一域名。如果看到 subject 那一行显示的是 *.herokuapp.com,那意味着我们需要把域名 CNAME 改为 herokudns.com,或者是域名变更还没生效。(变更还没在本地 DNS 生效的话,可以用 curl --resolve 在本地强行覆盖。)如果 Heroku 应用有多个域名,subject 会是其中一个,但 subjectAltName 会有多个域名,至少应该找到有一个对的。
最后,如果你喜欢我的文章的话,欢迎通过邮件或 RSS/Atom 订阅我的博客。
Heroku + Node.js + HTTPS的更多相关文章
- Node.js HTTPS
稳定性: 3 - 稳定 HTTPS 是基于 TLS/SSL 的 HTTP 协议.在 Node 里作为单独的模块来实现. 类: https.Server 这是 tls.Server 的子类,并且和 ht ...
- Node.js之路【第一篇】初识Node.js
什么是Node.js 1.Node.js就是运行在服务端的JavaScrip. 2.Node.js是一个基于Chrome JavaScrip运行时简历的一个平台. 3.Node.js是一个非阻塞I/O ...
- rabbitmq, windows/linux, c/c++/node.js/golang/dotnet
官网:http://www.rabbitmq.com/ zeromq 相当于 message backbone,而rabbitmq相当于message broker.有的应用系统中,二者并存. (1) ...
- aix 上搭建node.js 环境
下载nodejs:ibm-4.4.3.0-node-v4.4.3-aix-ppc64.bin IBM已经适配最新版本的node.js :https://developer.ibm.com/node/ ...
- Node.js:JavaScript脚本运行环境
Node.js https://nodejs.org/ 2016-08-03
- 安装Node.js
1.window下安装Node.js 安装git,方便使用命令行. 网址:http://www.git-scm.com/download/ 下载后直接安装即可 接着安装Node.js https:// ...
- 【 js 模块加载 】深入学习模块化加载(node.js 模块源码)
一.模块规范 说到模块化加载,就不得先说一说模块规范.模块规范是用来约束每个模块,让其必须按照一定的格式编写.AMD,CMD,CommonJS 是目前最常用的三种模块化书写规范. 1.AMD(Asy ...
- 使用node.js 脚手架搭建Vue项目
1.安装node.js https://nodejs.org/zh-cn/ 下载安装node.js 在命令行测试 node -v 输出版本号说明安装成功 2.使用npm更新安装cpnm npm ins ...
- Node.js作web服务器总结
1.为什么Node.js用JS开发 Node.js 含有一系列内置模块,使得程序可以脱离 Apache HTTP Server 或 IIS,作为独立服务器运行. 首先,我们都清楚的是,同时接收数 ...
随机推荐
- python 饥饿的小易(网易笔试题)
本周早些时候,学弟给我发了一道网易的笔试题,饥饿的小易,感觉有点意思-分享给大家 题目描述: 小易总是感觉饥饿,所以作为章鱼的小易经常出去寻找贝壳吃.最开始小易在一个初始位置x_0.对于小易所处的当前 ...
- MySQL mysqlbinlog解析出的SQL语句被注释是怎么回事
MySQL mysqlbinlog解析出的SQL语句被注释是怎么回事 一网友反馈使用mysqlbinlog解析出的二进制日志中的内容中,有些SQL语句有#注释的情况,这个是怎么回事呢?我们通过实验 ...
- spring4笔记----依赖注入的两种形式
设值注入:通过<property.../>元素驱动Spring执行setter的方法 构造注入:通过<constructor-arg.../>元素驱动Spring执行带有参数的 ...
- create table 使用select查询语句创建表的方法分享
转自:http://www.maomao365.com/?p=6642 摘要:下文讲述使用select查询语句建立新的数据表的方法分享 ---1 mysql create table `新数据表名` ...
- Lua保留指定小数位数
默认会四舍五入 比如:%0.2f 会四舍五入后,保留小数点后2位 print(string.format("%.1f",0.26)) ---会输出0.3,而不是0.2 Lua保留一 ...
- 如何进行Apache虚拟机设置
摘要:虚拟机Apache设置很多用户都遇到过,具体如何进行虚拟机Apache设置?怎样才能让虚拟机Apache设置达到最简单,最优化?本文为您讲解. Apache虚拟机设置有两种方法: 基于主机名的虚 ...
- ThreadLocal源码调试——“this”作为key
前言:在一次面试过程中被问到ThreadLocal,大家都知道ThreadLocal可以为每个线程单独提供一个副本,从而实现变量间的隔离.在ThreadLocal中set和get操作的key是什么,T ...
- Java基础知识点(二)
前言:Java的基础知识点不能间断. 1.Array和ArrayList的区别 关于Array的用法,参看:http://blog.csdn.net/b_11111/article/details/5 ...
- ElasticSearch(四):使用Java连接ElasticSearch集群
public class ESIndexMapping { private static String host="192.168.56.3"; // 服务器地址 private ...
- 2.05-random-uesr-proxy
import urllib.request def proxy_user(): proxy_list = [ {"https":""}, # {"ht ...