Как настроить HttpClient в функциях Azure

#.net-core #azure-functions

Вопрос:

Как и многие, я использую HttpClient в некоторых своих функциях Azure (v3.x). Проблема в том, что узел функций Azure использует HttpClient в качестве одного элемента. Это означает, что если я установлю заголовки в одной функции, они будут установлены для всех функций. Я хочу иметь разные заголовки (например, заголовки авторизации) в разных функциях. Является ли единственным способом добиться этого создание различных функциональных приложений для каждого набора заголовков, которые мне нужны?

Комментарии:

1. Вы должны иметь возможность использовать HttpClientFactory и настраивать именованные или типизированные клиенты.

Ответ №1:

Обычно вы не используете «глобальные HttpClient « DefaultRequestHeaders . Вы хотели бы создать HttpRequestMessage и использовать SendAsync . Это дает этому сеансу уникальный словарь заголовков, который отделен от всех других запросов.

HttpClient они DefaultRequestHeaders не являются потокобезопасными. Поэтому, если вы измените их в середине другого запроса, произойдет сбой.

Что вам следует сделать, так это внедрить HttpClientFactory , а затем создать из этого клиентов. Продолжайте использовать шаблон HttpRequestMessage / SendAsync (или используйте прямой GetAsync PostAsync , и т. Д.), Избегая DefaultRequestHeaders при этом (если вы используете заводской CreateClient() метод).

Если вы используете фабрику, вы можете использовать, DefaultRequestHeaders если создадите именованный или типизированный HttpClient объект с фабрики. Вероятно, вы захотите сделать это для своего конкретного случая использования, о котором вы упомянули в своем вопросе.

Пример

  1. Запустите новый проект функций Azure.
  2. Добавление Microsoft.Azure.Functions.Extensions и Microsoft.Extensions.Http пакеты через NuGet.
  3. Добавьте новый класс, назовите его Startup.cs . Сделай так, чтобы это выглядело так:
 using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
using System.Net.Http.Headers;

[assembly: FunctionsStartup(typeof(MyAzureFunction.Startup))]

namespace MyAzureFunction
{
    public sealed class Startup : FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {
            builder.Services.AddHttpClient("MyAuthorizedClient", client =>
            {
                client.DefaultRequestHeaders.Authorization =
                    new AuthenticationHeaderValue("Bearer", "<token>");
            });
        }
    }
}
 
  1. По умолчанию класс функции и сама функция являются static . Обязательно удалите static ключевое слово. Затем добавьте конструктор. Мы введем фабрику через конструктор:
 using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Extensions.Logging;
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;

namespace MyAzureFunction
{
    public sealed class Function1
    {
        private readonly IHttpClientFactory _httpClientFactory;

        public Function1(IHttpClientFactory httpContextFactory)
        {
            _httpClientFactory = httpContextFactory;
        }

        [FunctionName("Function1")]
        public async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log)
        {
            //
            // make a request on the authorized client
            var authorizedClient = _httpClientFactory.CreateClient("MyAuthorizedClient");
            
            using (var response = await authorizedClient
                .GetAsync(new Uri("https://www.example.com")))
            {
                var objRecved = await response.Content.ReadAsAsync<object>();

                return new OkObjectResult(new { data = objRecved });
            }

            //
            // make a request on the non-authorized client using it's own header collection
            var nonAuthorizedClient = _httpClientFactory.CreateClient();
            
            using (var request = new HttpRequestMessage(
                HttpMethod.Get, new Uri("https://www.example.com")))
            {
                request.Headers.Authorization =
                    new AuthenticationHeaderValue("Bearer", "<token>");
                using(var response = await nonAuthorizedClient.SendAsync(request))
                {
                    response.EnsureSuccessStatusCode();

                    var objRecved = await response.Content.ReadAsAsync<object>();

                    return new OkObjectResult(new { data = objRecved });
                }
            }
        }
    }
}

 

Комментарии:

1. Я получаю следующее, когда пытаюсь запустить приложение-функцию локально Microsoft.Azure.WebJobs.Host: Cannot bind parameter 'httpClientFactory' to type IHttpClientFactory. Make sure the parameter Type is supported by the binding .

2. @HisDivineShadow — упс.. Извини за это. Я обновил код.