現象
await page.goto('http://app:3000/')
とすると、以下のようなエラーが出る
Error: net::ERR_SSL_PROTOCOL_ERROR at http://app:3000/
at navigate (/node_modules/puppeteer/lib/FrameManager.js:121:37)
at process._tickCallback (internal/process/next_tick.js:68:7)
-- ASYNC --
at Frame.<anonymous> (/node_modules/puppeteer/lib/helper.js:111:15)
at Page.goto (/node_modules/puppeteer/lib/Page.js:629:49)
at Page.<anonymous> (/node_modules/puppeteer/lib/helper.js:112:23)
at index.js:35:16
at process._tickCallback (internal/process/next_tick.js:68:7)
https でもないのに net::ERR_SSL_PROTOCOL_ERROR
が起きる。
実際にアクセスログを見ると、
[2019-07-03 14:36:29] ERROR bad Request-Line `\x16\x03\x01(..snip..)'.
のように \x16\x03\x01
から始まっており、実際に SSL 通信を試みているように見える。
時々、何も変更していないのに時間をおくとアクセスできたりする
環境
- 公式の Docker イメージ
- Puppeteer:
1.18.1
- google-chrome-unstable:
77.0.3833.0-1
もしかして
http://app/
や http://app:3000/
のように、ドメイン部分に .
を含まない URL でアクセスしていませんかapp
をドメインにしていませんか。
対応方法
どうにかして http://app.local/
のように、トップレベルドメインを .local
などにしたアドレスでアクセスできるようにする。
原因予想
おそらく Chrome 内部で .
のないドメインに対する処理がアレ。
Chrome(Chromium?) が *.app
というドメインを HSTS の対象にしており、 app
という文字列で引っ掛けているため http://app/
が https を強制される。
-
HTTP Strict Transport Security
In the future, if the user types http:// or omits the scheme, HTTPS is the default. In fact, all requests for URLs in the current domain will be redirected to HTTPS.
-
Status: app is currently preloaded.
-
chromium//src/net/http/transport_security_state_static.json
// gTLDs and eTLDs are welcome to preload if they are interested. { "name": "android", "policy": "public-suffix", "mode": "force-https", "include_subdomains": true }, { "name": "app", "policy": "public-suffix", "mode": "force-https", "include_subdomains": true }, { "name": "bank", "policy": "public-suffix", "mode": "force-https", "include_subdomains": true }, ...
Thanks @hrysd!!!
これは Chrome のバグか?
Issue 794202: Should HSTS Preload List affect unqualified hostnames? によると http://app/
のような unqualified hostnames は、
As a result of ICANN's policy decisions, unqualified hostnames are effectively 'squatters', and should be considered deprecated and, as captured in SSAC policy, a security risk
squatter
: 無断居住者, 不法占有者
とのことで Wontfix です。 http://app/
は使うな!
起きうるパターン
というか、実際にハマった状況。
開発中の Web アプリのスクショ撮影を自動化するため、docker-compose で環境を作る。
---
version: '3'
services:
app:
build:
context: .
command: ['bundle', 'exec', 'rails', 'server']
screenshot:
build:
context: ./screenshot
command: ['node', 'screenshot.js']
いろいろ(app 側の起動待ちとか)やって http://app:3000
にアクセスしようとすると net::ERR_SSL_PROTOCOL_ERROR
でエラー。時々成功する
上記パターンの対応方法
http://app.local:3000
でアクセスできるように docker-compose.yml を修正する。app に対してnetworks.default.aliases
を設定するといける
---
version: '3'
services:
app:
build:
context: .
command: ['bundle', 'exec', 'rails', 'server']
networks:
default:
aliases:
- app.local
screenshot:
build:
context: ./screenshot
command: ['node', 'screenshot.js']
スクリプト側で http://app.local:3000/
にアクセスする。
await page.goto('http://app.local:3000/')
できました。