本番環境ではあまり使うことはない、検証環境を想定したサンプルを紹介します。
本来のIHttpClientFactoryの使い方や基本的なサンプルは下記を参考にしていただければと思います。
前提
- マイクロソフトが推奨するIHttpClientFactoryを使用して、HttpClientクライアントを取得する前提です。
- サンプルはWindows10 + Visual Studio 2019(ASP.NET Core 3.1)環境で確認しています。
サンプル
サンプルのプロジェクトや完全なソースコードは次で公開しています。
Contribute to nextdoorwith/example-aspdotnet3 development by…
既定のHttpClientのオプション指定方法
既定のHttpClientにオプションを指定するインターフェイスは用意されていません。
名前付きクライアントにオプションを指定するインターフェイスはあるので、既定のクライアントを意味するOptions.DefaultName(“”)を指定して、オプションを指定できます。
業務では名前付きクライアントか型付きクライアントを使用すると思うので、これは検証用のTIPSになると思います。
1 2 3 4 5 6 7 8 9 10 11 12 | 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エラーの例外が発生します。
1 2 3 4 5 6 7 8 | ... 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のエラーを無視して通信を行いたい場合、次のようにサーバ証明書の検証ロジックを変更することで実現できます。(この例では、「常に成功」を返す検証ロジックを追加しています。)
1 2 3 4 5 6 7 8 9 | 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の実装が必要になります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | { "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" } } } |
ログ出力の例は次の通りです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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エンコードされています。
また、出力されないヘッダがあることも注意してください。
1 2 3 4 5 | 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を実装することもできますが、上記と同様に取得できないヘッダ情報があったり、勝手にデコードされてたりするので正確ではありません。