「[[マイクロソフト系技術情報 Wiki>http://techinfoofmicrosofttech.osscons.jp/]]」は、「[[Open棟梁Project>https://github.com/OpenTouryoProject/]]」,「[[OSSコンソーシアム .NET開発基盤部会>https://www.osscons.jp/dotNetDevelopmentInfrastructure/]]」によって運営されています。 -[[戻る>WebAPI]] * 目次 [#sf757713] #contents *概要 [#e1a30627] .NETクライアントからHTTPリクエストを送る場合、 従来は、 -[[WebClientクラス>#c6b27e18]]や -[[WebRequest, WebResponseクラス>#t3ae0017]]を 使用していたが、こちらは設計が古いもよう。 新しくは、.NET Framework 4.5 では BCL 入りした~ System.Net.Http.dllの[[HttpClientクラス>#n074732e]]を使用する。 *HttpClientFactoryクラス [#o8484df8] **概要 [#x1009ff5] -[[HttpClientクラス>#n074732e]]のFactoryクラス -.NET Core 2.1 以降で使用できる。 ***特徴 [#l71c2c5d] [[HttpClientクラス>#n074732e]]の[[ハンドラ委任>#b3ba802e]]を構成可能。 -ネーミングや構成を管理 -[[HttpClientクラス>#n074732e]]のライフサイクルを管理 -[[クリーン・アーキテクチャ>https://dotnetdevelopmentinfrastructure.osscons.jp/index.php?%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%83%BB%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3]]っぽく[[Polly>#n00a0b49]]を統合 **使い方 [#tc023e91] ***基本的な使い方 [#q35be5a1] -設定([[DI]] Container に登録) -使う場所で呼び出す ***使い方のパターン [#n85b9971] -基本的には、~ Controllerに[[DI]](constructor注入)し、~ 使う場所で、CreateClient(Factoryメソッド)を呼び出す。 -Named Clientsでは、~ 名前を指定して、CreateClient(Factoryメソッド)を呼び出す。 -TypedClientsでは、 --指定の型に[[DI]]する。 --型には、以下がある。 ---クラス(constructor注入) ---インターフェイス(Refitのlive interface) ***サンプル [#id72d551] 下記の[[参考>#vf058f30]]ページを見て。 **参考 [#vf058f30] ***Microsoft Docs [#z9f204bb] -ASP.NET Core で IHttpClientFactory を使用して HTTP 要求を行う~ https://docs.microsoft.com/ja-jp/aspnet/core/fundamentals/http-requests -[[Polly>#n00a0b49]]~ 回復力の高いアプリケーションの実装 --カスタム HTTP 呼び出しの指数バックオフを含む再試行について~ https://docs.microsoft.com/ja-jp/dotnet/architecture/microservices/implement-resilient-applications/explore-custom-http-call-retries-exponential-backoff --HttpClientFactory を使用して回復力の高い HTTP 要求を実装する~ https://docs.microsoft.com/ja-jp/dotnet/architecture/microservices/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests ***その他 [#de3a6925] -HttpClientFactory の使い方(ASP.NET Core 2.1-preview1) - BEACHSIDE BLOG~ https://blog.beachside.dev/entry/2018/05/15/190000 -HttpClient よりも HttpClientFactory を利用したほうが良いかも - 世界のやまさ~ https://blog.nnasaki.com/entry/2019/10/04/143936 -ASP.NET Core 2.1にて追加されたHttpClientFactory(とその周辺)を試す - 時が癒す~ http://mrgchr.hatenablog.com/entry/2018/03/09/000000 *HttpClientクラス [#n074732e] .NET Framework 4.5 で BCL 入りした、高機能で使い勝手がいいAPI。 **サンプル [#u8db561a] ***GET [#hff0cdc1] // HttpClient private static HttpClient _httpClient = new HttpClient(); // 通信用の変数 HttpRequestMessage httpRequestMessage = null; HttpResponseMessage httpResponseMessage = null; // HttpRequestMessage (Method & RequestUri) httpRequestMessage = new HttpRequestMessage { Method = HttpMethod.Get, RequestUri = new Uri("http://localhost/・・・", }; // HttpRequestMessage (Headers & Content) httpRequestMessage.Headers.Authorization = new AuthenticationHeaderValue( "Basic", Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes( string.Format("{0}:{1}", "・・・", "・・・")))); httpRequestMessage.Headers.ExpectContinue = false; // HttpResponseMessage httpResponseMessage = await _httpClient.SendAsync(httpRequestMessage); response = await httpResponseMessage.Content.ReadAsStringAsync(); return (JObject)JsonConvert.DeserializeObject(response); ***POST [#vaee7008] POST については、[[上記GETのコード>#hff0cdc1]]の -Method = HttpMethod.Get ---> Method = HttpMethod.Post に変更。 -httpRequestMessage.Content プロパティを設定する。 // HttpClient private static HttpClient _httpClient = new HttpClient(); // HttpRequestMessage (Method & RequestUri) httpRequestMessage = new HttpRequestMessage { Method = HttpMethod.Post, RequestUri = new Uri("http://localhost/・・・", }; // HttpRequestMessage (Headers & Content) httpRequestMessage.Headers.Authorization = new AuthenticationHeaderValue( "Basic", Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes( string.Format("{0}:{1}", "・・・", "・・・")))); httpRequestMessage.Content = new FormUrlEncodedContent( new Dictionary<string, string> { { "grant_type", "authorization_code" }, { "code", code }, { "redirect_uri", System.Web.HttpUtility.HtmlEncode( "http://localhost/・・・") }, }); // HttpResponseMessage httpResponseMessage = await _httpClient.SendAsync(httpRequestMessage); response = await httpResponseMessage.Content.ReadAsStringAsync(); return JsonConvert.DeserializeObject<Dictionary<string, string>>(response); ***JSON [#j80b5c5e] JSONのPOSTについては、 >[[上記コード>#vaee7008]]のhttpRequestMessage.Content プロパティに[[JSON文字列を指定する>JSONのparseを色々試してみた。]]。 でイケる。と思う。 ちょっとコツがあった(以下のような感じ)。 httpRequestMessage.Content = new StringContent( JsonConvert.SerializeObject(new { language = "ja" }), Encoding.UTF8, "application/json"); **ポイント [#l0c18008] ***Make your HttpClient static. [#vf2acf0c] -以下の問題があるので、HttpClientは基本的に、 --staticで使用する。 --都度、instance化しないこと(適切にdisposeしてもダメ)。 --これは、都度、instanceすると、ソケットを爆発させるため。 -参考 --infoq.com ---開発者を苦しめる.NETのHttpClient~ のバグと紛らわしいドキュメント~ https://www.infoq.com/jp/news/2016/09/HttpClient ---.NETのHttpClientの修正~ https://www.infoq.com/jp/news/2018/03/HttpClientFactory/ --Qiita ---.NETのHttpClientの取り扱いには要注意という話~ https://qiita.com/nskhara/items/b7c31d60531ffbe29537 ---HttpClientをマルチスレッドで運用する場合の注意点~ https://qiita.com/skitoy4321/items/dc6bd2b62b62c2414642 -[[HttpClient × HttpClientFactory × より良い実装方法を調べてみた - きなこもち.net>https://www.kinakomotitti.net/entry/2021/04/03/164718#DIHttpClientFactory%E3%82%92%E3%81%A4%E3%81%8B%E3%81%A3%E3%81%9F%E4%BE%8B]] ***認証プロキシを通す場合 [#o5d5fc6b] 以下が参考になる。 -HttpClient で 認証プロキシ サーバーを使用するには – 荒井省三のBlog~ https://blogs.msdn.microsoft.com/shozoa/2014/09/02/httpclient/ ***デバッグ・プロシキを通す。 [#o2f9ed91] [[認証プロキシを通す場合>#o5d5fc6b]]と同じだが、 -[[Fiddler>電文を確認する方法(パケット・キャプチャ)#w11d3ad2]]は --「WebBrowser」はlocalhostでも表示されるが、 --「Non-Browser」(≒ HttpClient)はlocalhostが表示されない。 >という(非常に痛い)問題がある。~ (WebProxy.BypassProxyOnLocal辺りの問題と切り分けが困難) -以下の「http://localhost」をhostsファイルで別名に変更すると、~ 「Non-Browser」でも、ログに表示されるようになる。 using System; using System.Net.Http; namespace ConsoleApp1 { class Program { //private static readonly string proxyUrl = "http://127.0.0.1:8888"; //private static readonly string proxyAccount = "account"; //private static readonly string proxyPassword = "password"; private static readonly string targetUrl = "http://localhost/iisstart.htm"; static void Main(string[] args) { // HttpClientHandlerにProxy情報を設定する HttpClientHandler ch = new HttpClientHandler(); //ch.Proxy = new WebProxy(proxyUrl); //ch.Proxy.Credentials = new NetworkCredential(proxyAccount, proxyPassword); //ch.UseProxy = true; // HttpClientHandlerを用いてHttpClientを生成 HttpClient client = new HttpClient(ch); try { // GETでレスポンスを取得 var task = client.GetStringAsync(targetUrl); task.Wait(); Console.WriteLine(task.Result); } catch (Exception e) { Exception e2 = e.GetBaseException(); System.Console.WriteLine(e2.Message); } Console.ReadKey(); } } } ***証明書の検証を無効化する。 [#m56ca19e] handlerに以下を加える。 handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => { return true; }; handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => { return true; }; -参考 --.NET CoreのHttpClientで無効な証明書を無視する - Azureの小ネタ (改)~ https://statemachine.hatenablog.com/entry/2018/03/10/122306 ***その他のオプション [#i42fae72] ... -参考 --C# HttpClientでタイムアウトを設定する - け日記~ https://ohke.hateblo.jp/entry/2017/05/12/202832 --HttpClient で HTTP 圧縮を使う - kazuakix の日記~ https://blog.kazuakix.jp/entry/2014/09/12/000636 ***ハンドラ委任について。 [#b3ba802e] HttpClientには、ハンドラ委任と言う概念がある -HttpClientの実行前後のパイプラインに、~ HttpClientMessageHandlersを追加できる。 -ハンドラの構成には、[[HttpClientFactoryクラス>#o8484df8]]が使用される。 -参考 --ASP.NET Web API - ASP.NET の HttpClient メッセージ ハンドラー 4.x | Microsoft Docs~ https://docs.microsoft.com/ja-jp/aspnet/web-api/overview/advanced/httpclient-message-handlers **参考 [#a1eb1525] -HttpClient クラス (System.Net.Http)~ https://msdn.microsoft.com/ja-jp/library/system.net.http.httpclient.aspx -.NET TIPS:HttpClientクラスでWebページを取得するには?[C#、VB] - @IT~ http://www.atmarkit.co.jp/ait/articles/1501/06/news086.html -Web API よりも HttpClient に注目したい - しばやん雑記~ http://blog.shibayan.jp/entry/20120822/1345563275 -ASP.NET Web API シンプルな文字列の POST について - miso_soup3 Blog~ http://miso-soup3.hateblo.jp/entry/2014/06/02/000603 -HttpClient詳解、或いは非同期の落とし穴について~ http://www.slideshare.net/neuecc/httpclient *旧式のクラス [#bdaef9a5] **WebClientクラス [#c6b27e18] -.NETでHTTPリクエストを処理するための最古のAPI。 -内部では、[[WebRequest, WebResponseクラス>#t3ae0017]]が利用される。 ***サンプル [#l4163c6f] 以下が参考になる。 -DOBON.NET > .NET Tips: C#, VB.NET --WebClientクラスでWebページを取得するには? - @IT~ http://www.atmarkit.co.jp/ait/articles/0505/20/news138.html --ファイルをダウンロードし保存する~ http://dobon.net/vb/dotnet/internet/downloadfile.html --ファイルをダウンロードし表示する~ http://dobon.net/vb/dotnet/internet/webclientopenread.html ***参考 [#hd232f9a] -WebClient クラス (System.Net)~ https://msdn.microsoft.com/ja-jp/library/system.net.webclient.aspx **WebRequest, WebResponseクラス [#t3ae0017] [[Silverlight]]が[[SOAP]]サーバーと通信するケースが増えたため、追加されたAPI。 -WebClientとの違いは、 --WebRequest, WebResponseの2クラスに分割され、非同期対応がなされた。 --WebResponseを使用してRequestを送信し、CallbackでWebResponseを取得する。 -各クラスには以下の派生クラスがある。 --HttpWebRequest、FileWebRequest、FtpWebRequest --HttpWebResponse、FileWebResponse、FtpWebResponse -.NET CoreのHttpWebRequestについては、~ 内部的に[[HttpClientクラス>#n074732e]]をnewしてアクセスしているらしい。 ***サンプル [#cc8b82cf] 以下が参考になる。 -DOBON.NET > .NET Tips: C#, VB.NET~ --WebRequest/WebResponseクラスでWebページを取得するには? - @IT~ http://www.atmarkit.co.jp/ait/articles/0506/10/news122.html --WebRequest、WebResponseクラスを使ってファイルをダウンロードし表示する~ http://dobon.net/vb/dotnet/internet/webrequest.html ***参考 [#nccc74b8] -WebRequest クラス (System.Net)~ https://msdn.microsoft.com/ja-jp/library/system.net.webrequest.aspx -WebResponse クラス (System.Net)~ https://msdn.microsoft.com/ja-jp/library/system.net.webresponse.aspx *参考 [#j377dfef] **JavaScript [#pc312687] [[引っ越しました。>https://dotnetdevelopmentinfrastructure.osscons.jp/index.php?JavaScript%20%E3%81%AE%20HTTP%20Client]] ***jQuery.ajax() [#m5888cea] ***, etc. [#y14d9ffa] **障害処理ポリシー [#e8fa9d8f] ***[[Exponential Backoff(指数バックオフ)]] [#h201e45d] ***[[Polly(Retry, Circuit Breaker, Timeout, Bulkhead, Fallback)]] [#n00a0b49] ---- Tags: [[:プログラミング]], [[:通信技術]], [[:.NET開発]], [[:.NET Core]], [[:ASP.NET]], [[:ASP.NET Web API]]