Подтвердить что ты не робот

Один экземпляр HttpClient с разными заголовками аутентификации

Учитывая, что .net HttpClient был разработан с повторным использованием и предназначен для long alive и утечки памяти были сообщены в коротких экземплярах. Какие направляющие линии существуют там, где вы хотите совершать спокойные вызовы на заданную конечную точку с использованием разных токенов-носителей (или любого заголовка авторизации) при вызове конечной точки для нескольких пользователей?

private void CallEndpoint(string resourceId, string bearerToken) {
  httpClient.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("bearer", bearerToken);
  var response = await httpClient.GetAsync($"resource/{resourceid}");
}

Учитывая, что вышеуказанный код может быть вызван любым количеством потоков в веб-приложении, легко может быть, что заголовок, заданный в первой строке, не является тем же, который используется при вызове ресурса.

Не вызывая конкуренции с помощью блокировок и поддерживая веб-приложение без состояния, рекомендуемый подход к созданию и удалению HttpClients для одной конечной точки (моя текущая практика заключается в создании отдельного клиента на конечную точку)?


Жизненный цикл

Хотя HttpClient косвенно реализует IDisposable интерфейса, рекомендуемое использование HttpClient - это не утилизировать его после каждого запроса. Объект HttpClient предназначен для поскольку ваше приложение должно запрашивать HTTP-запросы. Наличие объекта существует по нескольким запросам, позволяет установить место DefaultRequestHeaders и не позволяет вам мешать как CredentialCache и CookieContainer по каждому запросу, так как это было необходимо с помощью HttpWebRequest.

4b9b3361

Ответ 1

Если ваши заголовки обычно будут одинаковыми, вы можете установить DefaultRequestHeaders. Но вам не нужно использовать это свойство для указания заголовков. Как вы определили, это просто не сработает, если у вас будет несколько потоков с использованием одного и того же клиента. Изменения в заголовках по умолчанию, сделанные в одном потоке, будут влиять на запросы, отправленные на другие потоки.

Хотя вы можете устанавливать заголовки по умолчанию на клиенте и применять их к каждому запросу, заголовки действительно являются свойствами запроса. Поэтому, когда заголовки специфичны для запроса, вы просто добавляете их в запрос.

request.Headers.Authorization = new AuthenticationHeaderValue("bearer", bearerToken);

Это означает, что вы не можете использовать упрощенные методы, которые не связаны с созданием HttpRequest. Вам нужно будет использовать

public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request)

documented здесь.

Пример методов GET и POST, выполненных с помощью метода расширения, который позволяет вам манипулировать заголовком запроса и более HttpRequestMessage перед его отправкой:

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

Затем они могут быть использованы следующим образом:

var response = await httpClient.GetAsync("token",
    x => x.Headers.Authorization = new AuthenticationHeaderValue("basic", clientSecret));