webentwicklung-frage-antwort-db.com.de

Warum funktioniert HttpClient BaseAddress nicht?

Betrachten Sie den folgenden Code, in dem BaseAddress einen partiellen URI-Pfad definiert.

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

Ich erwarte, dass dies eine GET Anfrage an http://something.com/api/resource/7 Ausführt. Aber das tut es nicht.

Nach einigem Suchen finde ich diese Frage und Antwort: HttpClient with BaseAddress . Der Vorschlag ist, / Am Ende des BaseAddress zu platzieren.

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

Es funktioniert immer noch nicht. Hier ist die Dokumentation: HttpClient.BaseAddress Was ist hier los?

235
Timothy Shields

Es stellt sich heraus, dass von den vier möglichen Permutationen, abschließende oder führende Schrägstriche in die BaseAddress und den relativen URI einzufügen oder auszuschließen, die an die GetAsync -Methode übergeben wurden - oder an jede andere Methode von HttpClient - nur eins Permutation funktioniert. Sie müssen setzen einen Schrägstrich am Ende des BaseAddress und Sie müssen nicht setzen einen Schrägstrich am Anfang Ihrer relativen URI, wie im Folgenden Beispiel.

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

Obwohl ich meine eigene Frage beantwortete, dachte ich, ich würde die Lösung hier beitragen, da dieses unfreundliche Verhalten wiederum nicht dokumentiert ist. Mein Kollege und ich haben den größten Teil des Tages damit verbracht, ein Problem zu beheben, das letztendlich durch die Seltsamkeit von HttpClient verursacht wurde.

550
Timothy Shields

Die Referenzauflösung wird durch RFC 3986 Uniform Resource Identifier (URI): Generic Syntax beschrieben. Und genau so soll es funktionieren. Um den Pfad des Basis-URI beizubehalten, müssen Sie am Ende des Basis-URI einen Schrägstrich einfügen und am Anfang des relativen URI einen Schrägstrich entfernen.

Wenn der Basis-URI einen nicht leeren Pfad enthält, verwirft die Zusammenführungsprozedur den letzten Teil (nach dem letzten /). Relevant Abschnitt :

5.2.3. Pfade zusammenführen

Der obige Pseudocode bezieht sich auf eine "Zusammenführungs" -Routine zum Zusammenführen einer Relativpfadreferenz mit dem Pfad der Basis-URI. Dies geschieht wie folgt:

  • Wenn der Basis-URI über eine definierte Berechtigungskomponente und einen leeren Pfad verfügt, geben Sie eine Zeichenfolge zurück, die aus "/" besteht und mit dem Pfad der Referenz verknüpft ist. Andernfalls

  • gibt eine Zeichenfolge zurück, die aus der Pfadkomponente der Referenz besteht, die an alle bis auf das letzte Segment des Basis-URI-Pfads angehängt ist (dh, alle Zeichen nach dem am weitesten rechts stehenden "/" im Basis-URI-Pfad werden ausgeschlossen, oder der gesamte Basis-URI-Pfad wird ausgeschlossen, wenn dies der Fall ist enthält keine "/" Zeichen).

Wenn der relative URI mit einem Schrägstrich beginnt, wird er als relativer URI mit absolutem Pfad bezeichnet. In diesem Fall ignoriert die Zusammenführungsprozedur alle Basis-URI-Pfade. Weitere Informationen finden Sie im Abschnitt 5.2.2. Transform References .

38
Leonid Vasilev

Alternativ - verwenden Sie BaseAddress überhaupt nicht. Setzen Sie die gesamte URL in GetAsync ()

0
userSteve

Stieß auf ein Problem mit dem HTTPClient, obwohl die Vorschläge immer noch nicht zur Authentifizierung führten. Es stellte sich heraus, dass ich ein abschließendes '/' in meinem relativen Pfad brauchte.

d.h.

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