概要
http/2を喋る環境でバックエンドがConnectionヘッダーやらの取り扱いがどんな感じなのか気になって調べた。RFCとかみてもきちんと定められていて無視するなり不正リクエストにするべきであるというのが決まりの模様。
Connection や Keep-Alive などの接続固有のヘッダーフィールドは HTTP/2 では禁止されています。 Chrome と Firefox は HTTP/2 レスポンスでこれらを無視しますが、 Safari は HTTP/2 仕様の要件に準拠しており、これらを含むレスポンスは読み込まれません。
クライアント -> LB(http or httpsをプロキシするタイプ) -> Nginx
とかでNginxなりでConnectionヘッダーを付与する場合はアプリケーション層までLBが除けるならここで削除する必要がある。
RFC
HTTP/2 does not use the Connection header field to indicate connection-specific header fields; in this protocol, connection- specific metadata is conveyed by other means. An endpoint MUST NOT generate an HTTP/2 message containing connection-specific header fields; any message containing connection-specific header fields MUST be treated as malformed (Section 8.1.2.6).
proxy-connectionとか固有のヘッダーについての言及は無い模様。実際どれくらいが当てはまるのかはちょっとRFCだけでは確認できなかった。
実験
http/2に対応したNginxコンテナを用意してNginxで強制的にConenctionヘッダーをつけた場合のクライアントの動作を確認する
curl
$ curl --version curl 7.64.1 (x86_64-apple-darwin19.0) libcurl/7.64.1 (SecureTransport) LibreSSL/2.8.3 zlib/1.2.11 nghttp2/1.39.2 Release-Date: 2019-03-27 Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp Features: AsynchDNS GSS-API HTTP2 HTTPS-proxy IPv6 Kerberos Largefile libz MultiSSL NTLM NTLM_WB SPNEGO SSL UnixSockets
curlのhttp/2バージョンの対応が必要。libcurlとかは適宜上げる必要がある。
> GET / HTTP/2 > Host: localhost > User-Agent: curl/7.64.1 > Accept: */* > * Connection state changed (MAX_CONCURRENT_STREAMS == 128)! * http2 error: Invalid HTTP header field was received: frame type: 1, stream: 1, name: [connection], value: [keep_alive] * HTTP/2 stream 0 was not closed cleanly: PROTOCOL_ERROR (err 1) * stopped the pause stream! * Connection #0 to host localhost left intact * Closing connection 0
不正なヘッダーを受け取ったと行ってcurlがエラーとなっている。
firefox
閲覧できた
opera
閲覧できた
safari
プロトコルエラー
chrome
証明書エラーから進めず(原因不明)
結果
不正ヘッダーに関してはクライアントの実装依存でエラーにするなり閲覧可能で無視するなり別れる模様。Safariが読み込まないのはまあ良いとして外部呼び出し時にhttp/2では不正と呼ばれるヘッダーが付けられてくると利用側的に対応が難しそう(そもそもそんあサービス使うなって話か)