web-dev-qa-db-fra.com

Pourquoi HttpClient BaseAddress ne fonctionne-t-il pas?

Considérez le code suivant, où BaseAddress définit un chemin d'URI partiel.

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");
}

Je m'attends à ce que cela effectue une demande GET à http://something.com/api/resource/7. Mais ce n'est pas le cas.

Après quelques recherches, je trouve cette question et réponse: HttpClient with BaseAddress . La suggestion est de placer / à la fin de la 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");
}

Cela ne fonctionne toujours pas. Voici la documentation: HttpClient.BaseAddress Que se passe-t-il ici?

235
Timothy Shields

Il s'avère que, parmi les quatre permutations possibles d'inclusion ou d'exclusion de barres obliques de fin ou avant sur le BaseAddress et que l'URI relatif est passé à la méthode GetAsync - ou selon toute autre méthode de HttpClient _ seulement n la permutation fonctionne. Vous devez placez une barre oblique à la fin de la BaseAddress, et vous ne devez pas placez une barre oblique au début de votre URI relatif, comme dans l'exemple suivant .

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");
}

Même si j'ai répondu à ma propre question, je me suis dit que j'apporterais la solution ici car, encore une fois, ce comportement inamical est sans papiers. Mon collègue et moi avons passé la majeure partie de la journée à essayer de résoudre un problème qui était finalement causé par cette bizarrerie de HttpClient.

550
Timothy Shields

La résolution de référence est décrite par identificateur de ressource uniforme (URI) RFC 3986: Syntaxe générique . Et c'est exactement comme ça que ça devait fonctionner. Pour préserver le chemin de l'URI de base, vous devez ajouter une barre oblique à la fin de l'URI de base et supprimer une barre oblique au début de l'URI relatif.

Si l'URI de base contient un chemin non vide, la procédure de fusion ignore sa dernière partie (après la dernière /). Pertinent section :

5.2.3. Fusionner les chemins

Le pseudo-code ci-dessus fait référence à une routine "fusion" pour fusionner une référence de chemin relatif avec le chemin de l'URI de base. Ceci est accompli comme suit:

  • Si l'URI de base a un composant d'autorité défini et un chemin vide, retournez une chaîne constituée de "/" concaténée avec le chemin de la référence; autrement

  • renvoie une chaîne constituée du composant de chemin de la référence ajouté à tout sauf le dernier segment du chemin de l'URI de base (c'est-à-dire, à l'exclusion des caractères après le "/" le plus à droite dans le chemin de l'URI de base, ou du chemin complet de l'URI de base s'il ne contient pas de caractères "/").

Si l'URI relatif commence par une barre oblique, cela s'appelle un URI relatif à chemin absolu. Dans ce cas, la procédure de fusion ignore tout le chemin de l'URI de base. Pour plus d'informations, consultez 5.2.2. Transformer les références section.

38
Leonid Vasilev

Sinon, n'utilisez pas du tout BaseAddress. Mettez l'URL entière dans GetAsync ()

0
userSteve

A rencontré un problème avec HTTPClient, même avec les suggestions, il n'a toujours pas pu l'obtenir pour s'authentifier. Il s'avère que j'avais besoin d'un '/' final dans mon chemin relatif.

c'est à dire.

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