アプリ開発ときどきアウトドア

主にJavaを使ったアプリ開発やトラブルシューティング等のノウハウ、キャンプや登山の紹介や体験談など。

1. システムエンジニアリング ASP.NET Core 実装技術

ASP.NET Core: IHttpClientFactoryの検証用サンプル

投稿日:2020年4月19日 更新日:

本番環境ではあまり使うことはない、検証環境を想定したサンプルを紹介します。
本来のIHttpClientFactoryの使い方や基本的なサンプルは下記を参考にしていただければと思います。

前提

  • マイクロソフトが推奨するIHttpClientFactoryを使用して、HttpClientクライアントを取得する前提です。
  • サンプルはWindows10 + Visual Studio 2019(ASP.NET Core 3.1)環境で確認しています。

サンプル

サンプルのプロジェクトや完全なソースコードは次で公開しています。

既定のHttpClientのオプション指定方法

既定のHttpClientにオプションを指定するインターフェイスは用意されていません。
名前付きクライアントにオプションを指定するインターフェイスはあるので、既定のクライアントを意味するOptions.DefaultName(“”)を指定して、オプションを指定できます。
業務では名前付きクライアントか型付きクライアントを使用すると思うので、これは検証用のTIPSになると思います。

public void ConfigureServices(IServiceCollection services)
{
...
    services.AddHttpClient(Options.DefaultName, options =>
    {
        options.BaseAddress = new Uri("https://localhost:44399");
        options.DefaultRequestHeaders.Add("X-ACCESS-KEY", "secret");
        options.DefaultRequestHeaders.Accept.Clear();
        options.DefaultRequestHeaders.Accept.Add(
            new MediaTypeWithQualityHeaderValue("application/json"));
    });
...

サーバ証明書のエラーを無視する方法

通常、サーバ証明書の有効期限やホスト名の検証に失敗すると、次のようにSSLエラーの例外が発生します。

...
System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.
 ---> System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure.
   at System.Net.Security.SslStream.StartSendAuthResetSignal(ProtocolToken message, AsyncProtocolRequest asyncRequest, ExceptionDispatchInfo exception)
...
--- End of stack trace from previous location where exception was thrown ---
   at System.Net.Security.SslStream.ThrowIfExceptional()
...

このようなSSLのエラーを無視して通信を行いたい場合、次のようにサーバ証明書の検証ロジックを変更することで実現できます。(この例では、「常に成功」を返す検証ロジックを追加しています。)

public void ConfigureServices(IServiceCollection services)
{
    services.AddHttpClient("bypass-ssl-validation")
        .ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler{ 
            ServerCertificateCustomValidationCallback = (
                httpRequestMessage, cert, certChain, policyErrors) => {
               return true;
            }
        });

この変更を行うと全てのサーバ証明書の検証が無効になってしまいセキュリティが低下するので、検証や開発環境に限定した使用を推奨します。もし本番環境でSSLエラーの問題を解決したい場合、サーバ証明書を正しいものに更新する、信頼するサーバ証明書として登録する等、別の方法を推奨します。

HttpClientの通信内容のロギング方法

名前付きクライアントの場合ですが、次のようにSystem.Net.Http.HttpClient.{名前}.ClientHandlerのログレベルをTraceに変更することでHTTP要求/応答のHTTPヘッダをログ出力できます。
HTTPボディをログ出力する場合、HttpClientHandlerの実装が必要になります。

{
  "Logging": {
    "LogLevel": {
      "Default": "Debug",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information",

      // HTTP要求/応答のロギング
      "System.Net.Http.HttpClient.Default.ClientHandler": "Trace",
      "System.Net.Http.HttpClient.basic.ClientHandler": "Trace",
      "System.Net.Http.HttpClient.bypass-ssl-validation.ClientHandler": "Trace"
    }
  }
}

ログ出力の例は次の通りです。

System.Net.Http.HttpClient.basic.LogicalHandler: Information: Start processing HTTP request GET https://localhost:44399/api/SampleApi?arg1=abcxyz!%23$%25%26_%3D-003&arg2=あいうえお
System.Net.Http.HttpClient.basic.ClientHandler: Information: Sending HTTP request GET https://localhost:44399/api/SampleApi?arg1=abcxyz!%23$%25%26_%3D-003&arg2=あいうえお
System.Net.Http.HttpClient.basic.ClientHandler: Trace: Request Headers:
X-ACCESS-KEY: secret
Accept: application/json

System.Net.Http.HttpClient.basic.ClientHandler: Information: Received HTTP response after 147.3151ms - OK
System.Net.Http.HttpClient.basic.ClientHandler: Trace: Response Headers:
Transfer-Encoding: chunked
Server: Microsoft-IIS/10.0
X-Powered-By: ASP.NET
Date: Sun, 19 Apr 2020 09:59:43 GMT
Content-Type: application/json; charset=utf-8

System.Net.Http.HttpClient.basic.LogicalHandler: Information: End processing HTTP request after 165.0041ms - OK

実際の通信は次のようになっています。
上記ではクエリ文字列の日本語がそのまま出力されていますが、実際には次のようにURLエンコードされています。
また、出力されないヘッダがあることも注意してください。

GET /api/SampleApi?arg1=abcxyz!%23$%25%26_%3D-003&arg2=%E3%81%82%E3%81%84%E3%81%86%E3%81%88%E3%81%8A HTTP/1.1
Host: localhost:8080
X-ACCESS-KEY: secret
Accept: application/json
Request-Id: |623d2d43-44...

正確な通信内容を確認したい場合はwiresharkやtcpdump等のパケットキャプチャツールの使用をお薦めします。
HTTP要求/応答をログ出力するDelegatingHandlerを実装することもできますが、上記と同様に取得できないヘッダ情報があったり、勝手にデコードされてたりするので正確ではありません。



(adsbygoogle = window.adsbygoogle || []).push({});


(adsbygoogle = window.adsbygoogle || []).push({});

-1. システムエンジニアリング, ASP.NET Core, 実装技術

執筆者:

関連記事

VisualStudioのIIS Expressで独自ドメインとSSL

シングルサインオンの検証等を想定し、開発環境の複数のWebアプリに独自ドメイン名+SSLを使用したい。 Visual Studio 2019で作成したWeb系プロジェクトを前提とし、IIS Expre …

slf4jで独自ログ項目を追加(MDC)

業務要件、障害発生時の処理追跡や証跡等、ログ出力に特定項目を含めたい場合があります。 共通のログ出力ユーティリティやライブラリを作って、その中でログ出力内容を変更しても良いのですが、MDC(Mappe …

保守運用

運用 と 保守 の 違い

若い頃は 運用 と 保守 の違いを調べても良くわからなかった… この辺を使い分けられる人をほとんど見たことない… ある事項が運用なのか保守なのかの話をすると認識が合わない&#8 …

初心者向けの最低限のviの使い方

新入社員やUnix/Linux未経験がviで苦戦するのをよく見ます。 ネットではコマンドの説明を主とした内容が多く、このような資料を見てviを使うと、モードの違いが分からず、思ったように編集できないこ …

システムエンジニアによる嫌われる勇気の実践

愚直に成果を出すことしか知らなかったシステムエンジニアが、デスマーチなプロジェクトで心を病みそうになったが、「嫌われる勇気」を読んで逆に強くなったお話です。 モノ作りが好きだが「コミュニケーションが苦 …