web-dev-qa-db-ja.com

HttpClient BaseAddressが機能しないのはなぜですか?

BaseAddressが部分的なURIパスを定義する次のコードを考えてください。

using (var handler = new HttpClientHandler())
using (var client = new HttpClient(handler))
{
    client.BaseAddress = new Uri("http://something.com/api");
    var response = await client.GetAsync("/resource/7");
}

これがhttp://something.com/api/resource/7へのGETリクエストを実行することを期待しています。しかしそうではありません。

いくつかの検索の後、私はこの質問と答えを見つけます: BaseAddressを持つHttpClient 。提案はBaseAddressの終わりに/を置くことです。

using (var handler = new HttpClientHandler())
using (var client = new HttpClient(handler))
{
    client.BaseAddress = new Uri("http://something.com/api/");
    var response = await client.GetAsync("/resource/7");
}

まだうまくいきません。これがドキュメントです: HttpClient.BaseAddress ここで何が起こっているのですか?

224
Timothy Shields

BaseAddressと、GetAsyncメソッドに渡される相対URI、またはその他のHttpClientメソッドの前後にスラッシュを含めるか除外するかの4つの可能な組み合わせのうち、oneのみ=置換はうまくいきます。次の例のように、あなたは必須スラッシュをBaseAddressの末尾に置き、あなたは必須あなたの相対URIの先頭にスラッシュを置かない[してはいけません]。

using (var handler = new HttpClientHandler())
using (var client = new HttpClient(handler))
{
    client.BaseAddress = new Uri("http://something.com/api/");
    var response = await client.GetAsync("resource/7");
}

私は自分自身の質問に答えたにもかかわらず、ここでも解決策に貢献したいと思いました。これもまた、この不親切な行動は文書化されていないためです。私の同僚と私は、この変わったHttpClientによって最終的に引き起こされる問題を解決しようと、一日の大半を費やしました。

517
Timothy Shields

参照解決は、 RFC 3986 URI(Uniform Resource Identifier):汎用構文 で記述されています。それがまさにそれが機能することになっていた方法です。ベースURIパスを保持するには、ベースURIの末尾にスラッシュを追加し、相対URIの先頭にスラッシュを削除する必要があります。

ベースURIに空でないパスが含まれている場合、マージプロシージャは最後の部分(最後の/の後)を破棄します。関連する section

5.2.3。パスを結合

上記の疑似コードは、相対パス参照をベースURIのパスとマージするための「マージ」ルーチンを指します。これは次のようにして行われます。

  • ベースURIに定義済みの権限コンポーネントと空のパスがある場合は、参照のパスと連結された "/"で構成される文字列を返します。さもないと

  • ベースURIのパスの最後のセグメントを除くすべてに追加された参照のパスコンポーネントからなる文字列を返します(つまり、ベースURIパスの右端の "/"の後の文字を除く、またはベースURIパス全体を除く)。 "/"文字は含まれません。

相対URIがスラッシュで始まる場合は、絶対パス相対URIと呼ばれます。この場合、マージ手順はすべての基本URIパスを無視します。詳細については、 5.2.2。変換参照 sectionを確認してください。

31
Leonid Vasilev

あるいは - BaseAddressを使用しないでください。 URL全体をGetAsync()に入れます

2
userSteve

まだ提案がそれを認証させることができなかったとしても、HTTPClientに関する問題に遭遇しました。相対パスの末尾に '/'が必要です。

すなわち.

var result = await _client.GetStringAsync(_awxUrl + "api/v2/inventories/?name=" + inventoryName);
var result = await _client.PostAsJsonAsync(_awxUrl + "api/v2/job_templates/" + templateId+"/launch/" , new {
                inventory = inventoryId
            });
0
Tony