HttpClient で 認証プロキシ サーバーを使用するには

.NET Framework 4.5 以降や Windows Phone、Windows ストア アプリで、http 通信に HttpClient クラスを使用することが多いと思います。HttpClient クラスを使用する場合に問題になるのが、プロキシ サーバーの有無でしょう。基本的な考え方としては、インターネット エクスプローラーに設定されているプロキシ設定を HttpClient は透過的に使用します。

例外的にインターネット エクスプローラーのプロキシ情報が、空になって HttpClient による通信が失敗するケースが報告されています。この事象に対する技術情報が公開されており、この技術情報によれば PC を再起動することで回復すると記述されています。

今度は、認証情報を必要とするプロキシ サーバーを使用する場合はどうしたら良いかという問題です。HttpClient クラスのドキュメントによれば、シンプルな解決方法としては HttpClientHandler を使用する方法になります。何故かと言えば、HttpClientHandler クラスが Proxy プロパティを持っているからです。ですから、HttpClientHandler のドキュメントにあるように HttpClient のコンストラクタに引数として渡す前に、プロキシを設定します。このような仕組みになっていると、Azure Mobile Service のように独自のクラス MobileServiceClient のように内部で HttpClient クラスを使用している場合にプロキシを設定するにはどうしたら良いでしょうかかという問題が起きます。このような時に役立つ記事として「HttpClientを認証プロキシに対応させる」や「HttpClientを簡単に認証プロキシに対応させることができるライブラリ、RuntimeProxyをつくりました」がありました。この記事に掲載されているコードを示します。

 //Handlerに設定
//ProxyはOSで設定したプロキシサーバーURLとポートが取得可能
//認証情報は取得できなかったのでPickerによって取得
HttpClientHandler handler = new HttpClientHandler();
handler.Proxy = WebRequest.DefaultWebProxy;
handler.Proxy.Credentials = new NetworkCredential(UserName, Password);
// 以降はどのようにHttpClientでコネクションしても接続できます。
HttpClient client = new HttpClient();
var s = await client.GetStringAsync("https://garicchi.com");

このコードを読んでいて、あれと思うことがありました。というのは、HttpClient クラスは内部的にインターネット エクスプローラーのプロキシ設定を利用するという事を考えたからです。たとえば、このコードが「new HttpClient(handler) 」となっていたら、このような疑問を持ちませんでした。要は、HttpClientHandler を HttpClient クラスに設定していないのに動くという疑問です。この疑問を解決するヒントは、「handler.Proxy = WebRequest.DefaultWebProxy」の記述になります。この記述は、デフォルト(インターネット エクスプローラー)のプロキシ設定を取得するということです。ということは、次のコードでも良いのではないかと考えられます。

 // デフォルト プロキシ情報を取得して、資格情報を設定する
var proxy = WebRequest.DefaultWebProxy;
proxy.Credentials = new NetworkCredential(UserName, Password);

私にはこのコードをテストする環境がないので、結果は不明ですが、デフォルト プロキシを設定するという意味において同じではないかと考えられます。テストできる環境を持ちの方がいらっしましたら、テストした結果をお知らせいただければと思います。