.NET FrameworkアプリでID/Password認証ありのproxyを突破する

# やりたかったコト

* BoxのSDKを使って、Box APIに接続しているが、そのコネクションを、認証ありのプロキシ経由にしたかった
* BoxのSDKは、.NET Core で使用していた

# できなかったコト

* `.Net Framework application`では、設定ファイル(App.config)を使用してプロキシの設定ができる
* しかし、`.Net Core console application`ではこれ(App.configでプロキシ設定)が実装されていない
    * 参考: https://stackoverflow.com/questions/43071409/how-to-configure-a-proxy-in-a-net-core-console-app
* ただ、設定ファイルではできないが、機能(Class)としては実装されている
    * MSの実装: https://docs.microsoft.com/ja-jp/dotnet/api/system.net.http.httpclienthandler.proxy?view=netframework-4.7.2
    * 関連issue: https://github.com/Azure/azure-cosmos-dotnet-v2/issues/434
* .NET側としては、HttpClientHandler使ってproxy設定してね！ってことだが・・
* BoxのSDKでは、HttpClientHandler使ってるけど、Proxyの設定は実装されていない・・
    * Boxの実装：https://github.com/box/box-windows-sdk-v2/blob/master/Box.V2/Request/HttpRequestHandler.cs
    * なぜなら、app.config使えばいいと思ってるから！(.Net Coreでは使えないのに！)

# やったコト

* .NET Coreじゃなきゃダメ、ってことがなかったので、.NET Frameworkで動くようにし、App.configでproxyの設定ができるようにした

## App.configでのproxy設定方法

### proxy設定なしの場合
defaultProxy項目自体なくてもよい

```xml
  <system.net>
    <defaultProxy enabled="false" useDefaultCredentials="false">
    </defaultProxy>
  </system.net>
```

### proxy設定あり(認証なし)の場合
参考: https://docs.microsoft.com/ja-jp/dotnet/framework/configure-apps/file-schema/network/proxy-element-network-settings

```xml
  <system.net>
    <defaultProxy enabled="true" useDefaultCredentials="true">
        <proxy usesystemdefault="true"/>
    </defaultProxy>
  </system.net>
```

### proxy設定あり(認証あり)の場合
参考: https://docs.microsoft.com/ja-jp/dotnet/framework/configure-apps/file-schema/network/module-element-network-settings

```xml
  <appSettings>
    <add key="http_proxy_url" value="http://[IP]:[Port]"/>
    <add key="proxy_user" value="hoge"/>
    <add key="proxy_pass" value="fuga"/>
  </appSettings>
  <system.net>
    <defaultProxy enabled="true" useDefaultCredentials="false">
      <module type="Sample.MyProxyModule, Sample"/>
    </defaultProxy>
  </system.net>
```

#### moduleの実装(Sample.MyProxyModule)

* Sample/MyProxyModule.cs
    * 後述のApp.configから設定値を取得しています

```cs
using System;
using System.Net;
using System.Configuration;

namespace Sample
{
    public class MyProxyModule : IWebProxy
    {
        /// <summary>
        /// 認証情報
        /// </summary>
        public ICredentials Credentials { get; set; }

        /// <summary>
        /// ProxyServer名を返却
        /// </summary>
        /// <param name="destination"></param>
        /// <returns></returns>
        public Uri GetProxy(Uri destination)
        {
            return new Uri(ConfigurationManager.AppSettings["http_proxy_url"]);
        }

        /// <summary>
        /// コンストラクタ
        /// </summary>
        public AuthProxyModule()
        {
            try
            {
                Credentials = new NetworkCredential(ConfigurationManager.AppSettings["proxy_user"], ConfigurationManager.AppSettings["proxy_pass"]);
            }
            catch (Exception ex)
            {
                // 適宜
                throw;
            }
        }

        /// <summary>
        /// host でプロキシサーバーを使用しない場合は true。それ以外の場合は false。
        /// </summary>
        public bool IsBypassed(Uri host)
        {
            return false;
        }
    }
}
```

* Sample/App.config
    * 認証情報をとりあえず、ここで設定。これは色々と方法あると思うので適宜。

```xml
  <appSettings>
    <add key="http_proxy_url" value="http://[IP]:[Port]"/>
    <add key="proxy_user" value="hoge"/>
    <add key="proxy_pass" value="fuga"/>
  </appSettings>
```

---
参考にさせていただきました。ありがとうございます:pray_tone2:
[nap3/relayCredentials: 認証のプロキシの情報を中継するモジュール](https://github.com/nap3/relayCredentials)
[c# - Is it possible to specify proxy credentials in your web.config? - Stack Overflow](https://stackoverflow.com/questions/186800/is-it-possible-to-specify-proxy-credentials-in-your-web-config)