はじめに
私はiOSプログラミングのエンジニアではなく、サーバーサイド(しかも.NET系)のため、解決策は提示せず、こういう問題が起きうるという紹介に留めさせていただきます。
経緯
あるiOSのSDKをバージョンアップしたところ、あるCDNからレスポンスが返ってこなくなってしまいました。
詳しく調査していくと、このSDKではバージョンアップに伴い、サードパーティー製のHTTPリクエスト・ライブラリをiOSネイティブのNSMutableURLRequestに移行したとのこと。
さらに再現する条件を絞り込むと
- HTTPでは再現しないが、HTTPSだと必ず発生する
- リクエストヘッダに「TE: chunked;q=0」を付けたときだけ発生する
- CDN側ではアクセスログが残っていない(レスポンスを返した記録がない)
ということが分かってきました。
HTTP/2が使われていた
前述の状況から、リクエスト時点での問題である可能性が高くなり、NSURLSessionTaskMetricsのnetworkProtocolNameを調べたところ、HTTP通信のときはhttp/1.1が使われている一方で HTTPS通信のときはHTTP/2が自動で選択されていました。
HTTP/2ではTEヘッダは基本的に不正なフォーマット
RFC7540 Section 8.1.2.2を読むと、
1つの例外を除き、HTTP/2ではconnection-specificヘッダ(RFC7230 Section 6.1)は不正な形式として扱うと書かれています。
TEヘッダは値が"trailers"の場合のみが許可されています。
つまり、CDN側は実装としては正しい動作をしていたわけです。
まとめ
単純に言えば、
- TEヘッダを使わない
というのが一番簡単な解決策です。
そうはいっても、アクセス先が常にHTTP/2に対応しているとは限りません。意図せずHTTP/1.1が選択され、レスポンスがチャンク化されると問題が起きるかもしれません。
前置きした通り、この記事ではその問題については言及しません。
逆に言うとiOS以外でも同様の問題は起き得ますので、気を付けましょうという記事でした。