HttpClientクラスでAutomaticDecompressionプロパティを使用してContent-Encoding
ヘッダに従った自動的なコンテンツの展開を行うと、Content-Encoding
ヘッダの値が空として取得される問題と、その対応策について。
以下の内容は2023年05月05日時点での状況に基づく。
前提・AutomaticDecompressionを使用した自動的な展開
はじめに前提知識として、HttpClientクラスで圧縮アルゴリズムを有効にする方法について。
まず、AutomaticDecompressionプロパティに対して有効にする圧縮アルゴリズムを指定したSocketsHttpHandlerもしくはHttpClientHandlerを作成する。 これにより、リクエスト送信時にAccept-Encoding
ヘッダが自動的に設定されるようになる。 これ以降ではSocketsHttpHandlerを使用する。
続いて、作成したSocketsHttpHandlerを使用するHttpClientを作成し、リクエストを送信する。 これにより、レスポンスとして返送されるContent-Encoding
ヘッダの内容に応じて、自動的にコンテンツが展開される。
このとき上記のコードにあるように、HttpResponseMessage.Content.Headers.ContentEncodingプロパティは、実際にサーバーから返送されたContent-Encoding
ヘッダの内容ではなく、常に空になる。
SocketsHttpHandlerはAutomaticDecompressionプロパティに従って自動的な展開を行うと同時に、それ以上展開が必要ない・ヘッダの内容が意味を成さないことを表すために、ContentEncodingを空に設定したHttpContentを返す動作になっている。
また同様に、HttpResponseMessage.Content.Headers.ContentLengthプロパティもnullに設定される動作になっている。
対応策
AutomaticDecompressionを無効にして自前で処理する
ContentEncodingおよびContentLengthが空(もしくはnull
)に設定される動作は、AutomaticDecompressionプロパティを使用して自動的な展開を行う場合に特有の動作となっている。
そこで、Accept-Encoding
ヘッダの設定およびContent-Encoding
ヘッダの取得、コンテンツの展開を手動で行うことにより、この問題を回避できる。 ただし、SocketsHttpHandler・HttpClientHandlerが内部で行っていることを再実装する形になるので、若干コードが複雑になる。
HttpResponseMessage.Contentの型情報から推測する (不完全)
AutomaticDecompressionプロパティを使用して自動的な展開を行った場合、HttpResponseMessage.Contentプロパティには展開済みのHttpContentが設定される。
そこで、HttpResponseMessage.Contentプロパティに設定されているオブジェクトの型情報を取得することによって、適用されていた圧縮アルゴリズムを推測する。
この方法では、Content-Encoding: deflate, gzip
のように複数の圧縮アルゴリズムが適用されていた場合は、最後に展開されたアルゴリズムのみしか推測することができない。 また、公開されていない型の型名に依存した判定方法であるため、将来の変更によって動作が変わる可能性があり、結果は保証されない。
その他の情報
カスタム処理を記述したDelegatingHandlerを既存処理に挟み込む方法については、公開APIを使ってレスポンスの受信からContent-Type
ヘッダの上書きまでの間にカスタム処理を挟み込む方法がないため、実装できない。