Angesichts der Tatsache, dass der .net HttpClient unter Berücksichtigung der Wiederverwendung entwickelt wurde und langlebig sein soll und in kurzlebigen Fällen Speicherlecks gemeldet wurden . In welchen Richtlinien möchten Sie einen bestimmten Endpunkt mit verschiedenen Inhaber-Token (oder einem beliebigen Berechtigungsheader) ruhig aufrufen, wenn Sie den Endpunkt für mehrere Benutzer aufrufen?
private void CallEndpoint(string resourceId, string bearerToken) {
httpClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("bearer", bearerToken);
var response = await httpClient.GetAsync($"resource/{resourceid}");
}
Da der obige Code von einer beliebigen Anzahl von Threads in einer Webanwendung aufgerufen werden kann, ist es leicht möglich, dass der in der ersten Zeile festgelegte Header nicht derselbe ist, der beim Aufrufen der Ressource verwendet wird.
Was ist der empfohlene Ansatz zum Erstellen und Entsorgen von HttpClients für einen einzelnen Endpunkt, ohne Konflikte durch Sperren und Verwalten einer zustandslosen Webanwendung zu verursachen (meine derzeitige Praxis besteht darin, einen einzelnen Client pro Endpunkt zu erstellen)?
Lebenszyklus
Obwohl HttpClient die IDisposable-Schnittstelle indirekt implementiert, besteht die empfohlene Verwendung von HttpClient nicht darin, sie nach jeder Anforderung zu entsorgen. Das HttpClient-Objekt soll so lange leben, wie Ihre Anwendung HTTP-Anforderungen stellen muss. Wenn ein Objekt über mehrere Anforderungen hinweg vorhanden ist, können Sie DefaultRequestHeaders festlegen und müssen nicht bei jeder Anforderung Dinge wie CredentialCache und CookieContainer erneut angeben, wie dies bei HttpWebRequest erforderlich war.
quelle
Antworten:
Wenn Ihre Header normalerweise gleich sind, können Sie die festlegen
DefaultRequestHeaders
. Sie müssen diese Eigenschaft jedoch nicht verwenden, um Header anzugeben. Wie Sie festgestellt haben, würde dies einfach nicht funktionieren, wenn Sie mehrere Threads mit demselben Client haben. Änderungen an den Standardheadern, die für einen Thread vorgenommen wurden, wirken sich auf Anforderungen aus, die an andere Threads gesendet werden.Obwohl Sie Standardheader auf dem Client festlegen und auf jede Anforderung anwenden können, sind die Header tatsächlich Eigenschaften der Anforderung. Wenn die Header für eine Anforderung spezifisch sind, fügen Sie sie einfach der Anforderung hinzu.
request.Headers.Authorization = new AuthenticationHeaderValue("bearer", bearerToken);
Das heißt, Sie können die vereinfachten Methoden nicht verwenden, bei denen keine erstellt wird
HttpRequest
. Sie müssen verwendenpublic Task<HttpResponseMessage> SendAsync(HttpRequestMessage request)
hier dokumentiert .
Einige fanden es hilfreich, Erweiterungsmethoden zu verwenden, um den Code, der die Header aktualisiert, vom Rest einer Methode zu isolieren.
Beispiel für GET- und POST-Methoden, die über eine Erweiterungsmethode ausgeführt werden, mit der Sie den Anforderungsheader und mehr davon bearbeiten können,
HttpRequestMessage
bevor er gesendet wird:public static Task<HttpResponseMessage> GetAsync (this HttpClient httpClient, string uri, Action<HttpRequestMessage> preAction) { var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, uri); preAction(httpRequestMessage); return httpClient.SendAsync(httpRequestMessage); } public static Task<HttpResponseMessage> PostAsJsonAsync<T> (this HttpClient httpClient, string uri, T value, Action<HttpRequestMessage> preAction) { var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, uri) { Content = new ObjectContent<T> (value, new JsonMediaTypeFormatter(), (MediaTypeHeaderValue)null) }; preAction(httpRequestMessage); return httpClient.SendAsync(httpRequestMessage); }
Diese könnten dann wie folgt verwendet werden:
var response = await httpClient.GetAsync("token", x => x.Headers.Authorization = new AuthenticationHeaderValue("basic", clientSecret));
quelle
HttpClientHandler.Proxy
ist mitHttpClientHandler.CookieContainer
und andere EigenschaftenHttpClientHandler
davon können nicht in der eingestellt werdenHttpRequestMessage
? (oder können sie?)Microsoft.Extensions.DependencyInjection
(IServiceCollection
), oder zumindest ist weniger klar, wie wir sie mit einem anderen IoC-Container oder keinem verwenden würden.