Реализация веб-сервера Kestrel в ASP.NET Core

Авторы: Том Дикстра (Tom Dykstra), Крис Росс (Chris Ross) и Стивен Хальтер (Stephen Halter)

Kestrel — это кроссплатформенный веб-сервер для ASP.NET Core. Kestrel по умолчанию включается в шаблоны проектов ASP.NET Core и активируется в них.

Kestrel поддерживается в следующих сценариях:

  • HTTPS
  • HTTP/2 (за исключением macOS†)
  • Непрозрачное обновление для поддержки WebSocket
  • Сокеты UNIX для повышения производительности при работе за Nginx

† HTTP/2 будет поддерживаться для macOS в будущих выпусках.

Kestrel поддерживается на всех платформах и во всех версиях, поддерживаемых .NET Core.

Просмотреть или скачать образец кода (как скачивать)

Начало работы

Шаблоны проектов ASP.NET Core используют Kestrel по умолчанию. В Program.cs метод ConfigureWebHostDefaults вызывает UseKestrel:

public static void Main(string[] args)
{
    CreateHostBuilder(args).Build().Run();
}

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        });

Дополнительные сведения о создании узла см. в разделах Настройка узла и Параметры построителя по умолчанию статьи Универсальный узел .NET в ASP.NET Core.

Необязательные сертификаты клиентов

Сведения о приложениях, которые должны защищать группу приложения с помощью сертификата, см. в разделе Необязательные сертификаты клиентов.

Дополнительные ресурсы

Примечание

Начиная с ASP.NET Core 5.0, транспорт Kestrel Libuv считается устаревшим. Транспорт libuv не получает обновления для включения поддержки новых платформ ОС, таких как Windows ARM64, и будет удален в будущем выпуске. Удалите все вызовы устаревшего метода UseLibuv и используйте вместо него транспорт Kestrel на основе сокетов по умолчанию.

Kestrel — это кроссплатформенный веб-сервер для ASP.NET Core. Kestrel — это веб-сервер, который по умолчанию включается в шаблоны проектов ASP.NET Core.

Kestrel поддерживается в следующих сценариях:

  • HTTPS
  • Непрозрачное обновление для поддержки WebSocket
  • Сокеты UNIX для повышения производительности при работе за Nginx
  • HTTP/2 (за исключением macOS†)

† HTTP/2 будет поддерживаться для macOS в будущих выпусках.

Kestrel поддерживается на всех платформах и во всех версиях, поддерживаемых .NET Core.

Просмотреть или скачать образец кода (как скачивать)

Поддержка HTTP/2

Протокол HTTP/2 доступен для приложений ASP.NET Core, если выполнены следующие базовые требования:

  • Операционная система†:
    • Windows Server 2016 / Windows 10 или более поздних версий‡
    • Linux с OpenSSL 1.0.2 или более поздней версии (например, Ubuntu 16.04 или более поздней версии).
  • Требуемая версия .NET Framework: .NET Core версии 2.2 или более поздней
  • Подключение с поддержкой согласования протокола уровня приложений (ALPN).
  • Подключение TLS 1.2 или более поздней версии.

† HTTP/2 будет поддерживаться для macOS в будущих выпусках. ‡ Kestrel имеет ограниченную поддержку HTTP/2 в Windows Server 2012 R2 и Windows 8.1. Поддержка ограничена из-за небольшого числа поддерживаемых комплектов шифров TLS, доступных для этих операционных систем. Для обеспечения безопасности TLS-подключений может потребоваться сертификат, созданный с использованием алгоритма ECDSA.

Если установлено подключение HTTP/2, HttpRequest.Protocol возвращает HTTP/2.

Начиная с версии .NET Core 3.0 протокол HTTP/2 по умолчанию включен. Дополнительные сведения о конфигурации см. в разделах, посвященных параметрам Kestrel и ListenOptions.Protocols.

Использование Kestrel с обратным прокси-сервером

Kestrel можно использовать отдельно или с обратным прокси-сервером, таким как IIS, Nginx или Apache. Обратный прокси-сервер получает HTTP-запросы из сети и пересылает их в Kestrel.

Kestrel используется в качестве пограничного (с выходом в Интернет) веб-сервера:

Kestrel взаимодействует с Интернетом напрямую без обратного прокси-сервера

Kestrel используется в конфигурации обратного прокси-сервера.

Kestrel косвенно обменивается данными с Интернетом через обратный прокси-сервер, такой как IIS, Nginx или Apache

Любая из этих конфигураций — с обратным прокси-сервером и без него — является поддерживаемой конфигурацией для размещения.

Kestrel, используемый в качестве пограничного сервера без обратного прокси-сервера, не поддерживает обращение нескольких процессов к одним и тем же IP-адресам и портам. Когда Kestrel настроен на прослушивание порта, Kestrel обрабатывает весь трафик для этого порта независимо от заголовков запросов Host. Обратный прокси-сервер, который может совместно использовать порты, также может пересылать запросы в Kestrel с уникальными IP-адресом и портом.

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

Обратный прокси-сервер:

  • Может ограничить общедоступную контактную зону размещенных на нем приложений.
  • Предоставляет дополнительный уровень конфигурации и защиты.
  • Может лучше интегрироваться с существующей инфраструктурой.
  • Упрощает настройку балансировки нагрузки и безопасных подключений (HTTPS). Сертификат X.509 требуется только обратному прокси-серверу, а сам этот сервер может обмениваться данными с серверами приложения во внутренней сети по обычному протоколу HTTP.

Предупреждение

Для размещения в конфигурации обратного прокси-сервера требуется конфигурация ПО промежуточного слоя перенаправленных заголовков.

Kestrel в приложениях ASP.NET Core

Шаблоны проектов ASP.NET Core используют Kestrel по умолчанию. В Program.cs метод ConfigureWebHostDefaults вызывает UseKestrel:

public static void Main(string[] args)
{
    CreateHostBuilder(args).Build().Run();
}

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        });

Дополнительные сведения о создании узла см. в разделах Настройка узла и Параметры построителя по умолчанию статьи Универсальный узел .NET в ASP.NET Core.

Чтобы задать дополнительную конфигурацию после вызова ConfigureWebHostDefaults, используйте ConfigureKestrel:

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.ConfigureKestrel(serverOptions =>
            {
                // Set properties and call methods on options
            })
            .UseStartup<Startup>();
        });

Параметры Kestrel

Веб-сервер Kestrel имеет ограничивающие параметры конфигурации, которые удобно использовать в развертываниях с выходом в Интернет.

Задать ограничения для свойства Limits в классе KestrelServerOptions. Свойство Limits содержит экземпляр класса KestrelServerLimits.

В следующих примерах используется пространство имен Microsoft.AspNetCore.Server.Kestrel.Core.

using Microsoft.AspNetCore.Server.Kestrel.Core;

В примерах, приведенных далее в этой статье, параметры Kestrel настраиваются в коде C#. Параметры Kestrel можно также задать с помощью поставщика конфигурации. Например, поставщик конфигурации файла может загрузить конфигурацию Kestrel из файла appsettings.json или appsettings.{Environment}.json:

{
  "Kestrel": {
    "Limits": {
      "MaxConcurrentConnections": 100,
      "MaxConcurrentUpgradedConnections": 100
    },
    "DisableStringReuse": true
  }
}

Примечание

KestrelServerOptions и конфигурацию конечных точек можно настроить из поставщиков конфигурации. Оставшаяся конфигурация Kestrel должна настраиваться в коде C#.

Воспользуйтесь одним из перечисленных ниже подходов.

  • Настройте Kestrel в Startup.ConfigureServices:

    1. Внедрение экземпляра IConfiguration в класс Startup. В следующем примере предполагается, что введенная конфигурация назначается свойству Configuration.

    2. В Startup.ConfigureServices загрузите раздел конфигурации Kestrel в конфигурацию Kestrel:

      using Microsoft.Extensions.Configuration
      
      public class Startup
      {
          public Startup(IConfiguration configuration)
          {
              Configuration = configuration;
          }
      
          public IConfiguration Configuration { get; }
      
          public void ConfigureServices(IServiceCollection services)
          {
              services.Configure<KestrelServerOptions>(
                  Configuration.GetSection("Kestrel"));
          }
      
          public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
          {
              ...
          }
      }
      
  • Настройте Kestrel при создании узла:

    В Program.cs загрузите раздел конфигурации Kestrel в конфигурацию Kestrel.

    // using Microsoft.Extensions.DependencyInjection;
    
    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureServices((context, services) =>
            {
                services.Configure<KestrelServerOptions>(
                    context.Configuration.GetSection("Kestrel"));
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
    

Оба предыдущих подхода работают с любым поставщиком конфигурации.

Время ожидания проверки на активность

KeepAliveTimeout

Получает или задает время ожидания проверки на активность. Значение по умолчанию — 2 минуты.

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.Limits.MaxConcurrentConnections = 100;
    serverOptions.Limits.MaxConcurrentUpgradedConnections = 100;
    serverOptions.Limits.MaxRequestBodySize = 10 * 1024;
    serverOptions.Limits.MinRequestBodyDataRate =
        new MinDataRate(bytesPerSecond: 100, 
            gracePeriod: TimeSpan.FromSeconds(10));
    serverOptions.Limits.MinResponseDataRate =
        new MinDataRate(bytesPerSecond: 100, 
            gracePeriod: TimeSpan.FromSeconds(10));
    serverOptions.Listen(IPAddress.Loopback, 5000);
    serverOptions.Listen(IPAddress.Loopback, 5001, 
        listenOptions =>
        {
            listenOptions.UseHttps("testCert.pfx", 
                "testPassword");
        });
    serverOptions.Limits.KeepAliveTimeout = 
        TimeSpan.FromMinutes(2);
    serverOptions.Limits.RequestHeadersTimeout = 
        TimeSpan.FromMinutes(1);
})

максимальное число клиентских подключений;

MaxConcurrentConnections MaxConcurrentUpgradedConnections

Максимальное число одновременно открытых подключений TCP для всего приложения можно задать с помощью следующего кода:

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.Limits.MaxConcurrentConnections = 100;
    serverOptions.Limits.MaxConcurrentUpgradedConnections = 100;
    serverOptions.Limits.MaxRequestBodySize = 10 * 1024;
    serverOptions.Limits.MinRequestBodyDataRate =
        new MinDataRate(bytesPerSecond: 100, 
            gracePeriod: TimeSpan.FromSeconds(10));
    serverOptions.Limits.MinResponseDataRate =
        new MinDataRate(bytesPerSecond: 100, 
            gracePeriod: TimeSpan.FromSeconds(10));
    serverOptions.Listen(IPAddress.Loopback, 5000);
    serverOptions.Listen(IPAddress.Loopback, 5001, 
        listenOptions =>
        {
            listenOptions.UseHttps("testCert.pfx", 
                "testPassword");
        });
    serverOptions.Limits.KeepAliveTimeout = 
        TimeSpan.FromMinutes(2);
    serverOptions.Limits.RequestHeadersTimeout = 
        TimeSpan.FromMinutes(1);
})

Существует отдельный предел по подключениям, измененным с HTTP или HTTPS на другой протокол (например, по запросу WebSocket). После изменения подключение не учитывается в пределе MaxConcurrentConnections.

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.Limits.MaxConcurrentConnections = 100;
    serverOptions.Limits.MaxConcurrentUpgradedConnections = 100;
    serverOptions.Limits.MaxRequestBodySize = 10 * 1024;
    serverOptions.Limits.MinRequestBodyDataRate =
        new MinDataRate(bytesPerSecond: 100, 
            gracePeriod: TimeSpan.FromSeconds(10));
    serverOptions.Limits.MinResponseDataRate =
        new MinDataRate(bytesPerSecond: 100, 
            gracePeriod: TimeSpan.FromSeconds(10));
    serverOptions.Listen(IPAddress.Loopback, 5000);
    serverOptions.Listen(IPAddress.Loopback, 5001, 
        listenOptions =>
        {
            listenOptions.UseHttps("testCert.pfx", 
                "testPassword");
        });
    serverOptions.Limits.KeepAliveTimeout = 
        TimeSpan.FromMinutes(2);
    serverOptions.Limits.RequestHeadersTimeout = 
        TimeSpan.FromMinutes(1);
})

По умолчанию максимальное число подключений не ограничено (null).

максимальный размер текста запроса;

MaxRequestBodySize

По умолчанию максимальный размер текста запроса составляет 30 000 000 байт, что примерно соответствует 28,6 МБ.

Чтобы переопределить это ограничение в приложении MVC ASP.NET Core, мы рекомендуем использовать атрибут RequestSizeLimitAttribute в методе действия:

[RequestSizeLimit(100000000)]
public IActionResult MyActionMethod()

Приведенный ниже пример показывает, как настроить ограничение для приложения и каждого запроса:

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.Limits.MaxConcurrentConnections = 100;
    serverOptions.Limits.MaxConcurrentUpgradedConnections = 100;
    serverOptions.Limits.MaxRequestBodySize = 10 * 1024;
    serverOptions.Limits.MinRequestBodyDataRate =
        new MinDataRate(bytesPerSecond: 100, 
            gracePeriod: TimeSpan.FromSeconds(10));
    serverOptions.Limits.MinResponseDataRate =
        new MinDataRate(bytesPerSecond: 100, 
            gracePeriod: TimeSpan.FromSeconds(10));
    serverOptions.Listen(IPAddress.Loopback, 5000);
    serverOptions.Listen(IPAddress.Loopback, 5001, 
        listenOptions =>
        {
            listenOptions.UseHttps("testCert.pfx", 
                "testPassword");
        });
    serverOptions.Limits.KeepAliveTimeout = 
        TimeSpan.FromMinutes(2);
    serverOptions.Limits.RequestHeadersTimeout = 
        TimeSpan.FromMinutes(1);
})

Переопределите параметр для конкретного запроса в ПО промежуточного слоя:

app.Run(async (context) =>
{
    context.Features.Get<IHttpMaxRequestBodySizeFeature>()
        .MaxRequestBodySize = 10 * 1024;

    var minRequestRateFeature = 
        context.Features.Get<IHttpMinRequestBodyDataRateFeature>();
    var minResponseRateFeature = 
        context.Features.Get<IHttpMinResponseDataRateFeature>();

    if (minRequestRateFeature != null)
    {
        minRequestRateFeature.MinDataRate = new MinDataRate(
            bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    }

    if (minResponseRateFeature != null)
    {
        minResponseRateFeature.MinDataRate = new MinDataRate(
            bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    }

Если приложение пытается настроить ограничение для запроса после того, как оно начало считывать запрос, возникает исключение. Доступно свойство IsReadOnly, указывающее, что свойство MaxRequestBodySize находится в состоянии только для чтения и настраивать ограничение слишком поздно.

При запуске приложения вне процесса, который обслуживает модуль ASP.NET Core, ограничение на размер текста запроса Kestrel будет отключено, так как оно уже задается IIS.

минимальная скорость передачи данных в тексте запроса.

MinRequestBodyDataRate MinResponseDataRate

Kestrel каждую секунду проверяет, поступают ли данные с указанной скоростью в байтах в секунду. Если скорость падает ниже минимума, для подключения истекает время ожидания. Льготный период — это время, которое Kestrel предоставляет клиенту для увеличения скорости отправки до минимального уровня; в течение этого периода скорость не проверяется. Льготный период помогает избежать разрыва соединений, которые первоначально отправляют данные с небольшой скоростью из-за медленного запуска TCP.

Минимальная скорость по умолчанию составляет 240 байт/с, льготный период равен 5 секундам.

Минимальная скорость также применяется к отклику. Код для задания лимита запросов и лимита откликов различается только наличием RequestBody или Response в именах свойств и интерфейсов.

Ниже приведен пример, показывающий, как настроить минимальную скорость передачи данных в Program.cs:

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.Limits.MaxConcurrentConnections = 100;
    serverOptions.Limits.MaxConcurrentUpgradedConnections = 100;
    serverOptions.Limits.MaxRequestBodySize = 10 * 1024;
    serverOptions.Limits.MinRequestBodyDataRate =
        new MinDataRate(bytesPerSecond: 100, 
            gracePeriod: TimeSpan.FromSeconds(10));
    serverOptions.Limits.MinResponseDataRate =
        new MinDataRate(bytesPerSecond: 100, 
            gracePeriod: TimeSpan.FromSeconds(10));
    serverOptions.Listen(IPAddress.Loopback, 5000);
    serverOptions.Listen(IPAddress.Loopback, 5001, 
        listenOptions =>
        {
            listenOptions.UseHttps("testCert.pfx", 
                "testPassword");
        });
    serverOptions.Limits.KeepAliveTimeout = 
        TimeSpan.FromMinutes(2);
    serverOptions.Limits.RequestHeadersTimeout = 
        TimeSpan.FromMinutes(1);
})

Переопределите ограничения минимальной скорости для каждого запроса в ПО промежуточного слоя:

app.Run(async (context) =>
{
    context.Features.Get<IHttpMaxRequestBodySizeFeature>()
        .MaxRequestBodySize = 10 * 1024;

    var minRequestRateFeature = 
        context.Features.Get<IHttpMinRequestBodyDataRateFeature>();
    var minResponseRateFeature = 
        context.Features.Get<IHttpMinResponseDataRateFeature>();

    if (minRequestRateFeature != null)
    {
        minRequestRateFeature.MinDataRate = new MinDataRate(
            bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    }

    if (minResponseRateFeature != null)
    {
        minResponseRateFeature.MinDataRate = new MinDataRate(
            bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    }

Возможности IHttpMinResponseDataRateFeature, указанные в предыдущем примере, отсутствуют в HttpContext.Features для запросов HTTP/2, так как изменение ограничений скорости для каждого запроса не поддерживается для HTTP/2 из-за поддержки протокола мультиплексирования запроса. Но возможности IHttpMinRequestBodyDataRateFeature все еще присутствуют в HttpContext.Features для запросов HTTP/2, так как ограничение скорости чтения может быть полностью отключено для отдельных запросов. Чтобы сделать это, задайте для параметра IHttpMinRequestBodyDataRateFeature.MinDataRate значение null (даже для запроса HTTP/2). При попытке чтения свойства IHttpMinRequestBodyDataRateFeature.MinDataRate или при попытке задать для него значение, отличное от null, возникнет исключение NotSupportedException для запроса HTTP/2.

Ограничения скорости на уровне сервера, которые настроены с помощью KestrelServerOptions.Limits, по-прежнему применяются к подключениям HTTP/1.x и HTTP/2.

Время ожидания для заголовков запросов

RequestHeadersTimeout

Получает или задает максимальное время, которое сервер уделяет получению заголовков запросов. Значение по умолчанию — 30 секунд.

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.Limits.MaxConcurrentConnections = 100;
    serverOptions.Limits.MaxConcurrentUpgradedConnections = 100;
    serverOptions.Limits.MaxRequestBodySize = 10 * 1024;
    serverOptions.Limits.MinRequestBodyDataRate =
        new MinDataRate(bytesPerSecond: 100, 
            gracePeriod: TimeSpan.FromSeconds(10));
    serverOptions.Limits.MinResponseDataRate =
        new MinDataRate(bytesPerSecond: 100, 
            gracePeriod: TimeSpan.FromSeconds(10));
    serverOptions.Listen(IPAddress.Loopback, 5000);
    serverOptions.Listen(IPAddress.Loopback, 5001, 
        listenOptions =>
        {
            listenOptions.UseHttps("testCert.pfx", 
                "testPassword");
        });
    serverOptions.Limits.KeepAliveTimeout = 
        TimeSpan.FromMinutes(2);
    serverOptions.Limits.RequestHeadersTimeout = 
        TimeSpan.FromMinutes(1);
})

Максимальное число потоков на подключение

Http2.MaxStreamsPerConnection ограничивает количество параллельных потоков запросов для одного соединения HTTP/2. Потоки сверх этого числа будут отклонены.

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.Limits.Http2.MaxStreamsPerConnection = 100;
});

Значение по умолчанию — 100.

Размер таблицы заголовка

Декодер HPACK распаковывает заголовки HTTP для подключений HTTP/2. Http2.HeaderTableSize ограничивает размер таблицы сжатия заголовка, которую использует декодер HPACK. Это значение указывается в октетах и должно быть больше нуля (0).

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.Limits.Http2.HeaderTableSize = 4096;
});

Значение по умолчанию — 4096.

Максимальный размер кадра

Http2.MaxFrameSize указывает максимально допустимый размер полезных данных в кадре подключения HTTP/2, получаемых или отправляемых сервером. Это значение указывается в октетах и должно находиться в пределах от 2^14 (16 384) до 2^24-1 (16 777 215).

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.Limits.Http2.MaxFrameSize = 16384;
});

Значение по умолчанию — 2^14 (16 384).

Максимальный размер запроса заголовка

Http2.MaxRequestHeaderFieldSize указывает максимально допустимый размер значений заголовка запроса (в октетах). Это ограничение применяется к имени и значению в их сжатых и несжатых представлениях. Значение должно быть больше нуля.

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.Limits.Http2.MaxRequestHeaderFieldSize = 8192;
});

Значение по умолчанию — 8 192.

Размер окна начального подключения

Http2.InitialConnectionWindowSize указывает максимальное значение данных тела запроса (в байтах), буферизируемое сервером за один раз, для всех запросов (потоков) на каждое соединение. Размеры запросов также ограничиваются параметром Http2.InitialStreamWindowSize. Значение должно быть больше или равно 65 535 и меньше 2^31 (2 147 483 648).

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.Limits.Http2.InitialConnectionWindowSize = 131072;
});

Значение по умолчанию — 128 КБ (131 072).

Размер окна начального потока

Http2.InitialStreamWindowSize указывает максимальное значение данных тела запроса (в байтах), буферизируемое сервером за один раз, для каждого запроса (потока). Размеры запросов также ограничиваются параметром Http2.InitialConnectionWindowSize. Значение должно быть больше или равно 65 535 и меньше 2^31 (2 147 483 648).

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.Limits.Http2.InitialStreamWindowSize = 98304;
});

Значение по умолчанию — 96 КБ (98 304).

Трейлеры

Трейлеры HTTP похожи на заголовки HTTP, за исключением того, что они отправляются после отправки текста ответа. Для IIS и HTTP.sys поддерживаются только трейлеры ответов HTTP/2.

if (httpContext.Response.SupportsTrailers())
{
    httpContext.Response.DeclareTrailer("trailername"); 

    // Write body
    httpContext.Response.WriteAsync("Hello world");

    httpContext.Response.AppendTrailer("trailername", "TrailerValue");
}

В приведенном выше примере кода:

  • SupportsTrailers обеспечивает поддержку трейлеров для ответа;
  • DeclareTrailer добавляет заданное имя трейлера в заголовок ответа Trailer. Объявлять трейлеры ответа необязательно, но рекомендуется. Вызов DeclareTrailer должен производиться перед отправкой заголовков ответа.
  • AppendTrailer добавляет трейлер.

Reset

Сброс позволяет серверу сбросить запрос HTTP/2 с указанным кодом ошибки. Сброшенный запрос считается прерванным.

var resetFeature = httpContext.Features.Get<IHttpResetFeature>();
resetFeature.Reset(errorCode: 2);

Reset в предыдущем примере кода задает код ошибки INTERNAL_ERROR. Дополнительные сведения о кодах ошибок HTTP/2 см. в соответствующем разделе спецификации HTTP/2.

Синхронный ввод-вывод

AllowSynchronousIO определяет, разрешены ли синхронные операции ввода-вывода для запроса и ответа. Значение по умолчанию — false.

Предупреждение

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

В примере ниже включаются синхронные операции ввода-вывода:

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.AllowSynchronousIO = true;
})

Сведения о других параметрах и ограничениях Kestrel см. в следующих разделах:

Конфигурация конечной точки

По умолчанию платформа ASP.NET Core привязана к:

  • http://localhost:5000
  • https://localhost:5001 (если присутствует локальный сертификат разработки)

Укажите URL-адреса с помощью следующих параметров:

  • Переменная среды ASPNETCORE_URLS.
  • Аргументы командной строки --urls.
  • Ключ конфигурации узла urls.
  • Метод расширения UseUrls.

Значение, указанное с помощью этих подходов, может быть одной или несколькими конечными точками HTTP и HTTPS (HTTPS при наличии сертификата по умолчанию). Настройте значение в виде списка с разделением точкой с запятой (например, "Urls": "http://localhost:8000;http://localhost:8001").

Дополнительные сведения о таких подходах см. в разделах URL-адреса сервера и Переопределение конфигурации.

Сертификат разработки создается, когда:

В некоторых браузерах требуется явное разрешение доверять локальному сертификату разработки.

Шаблоны проектов настраивают приложения так, чтобы они запускались на базе HTTPS по умолчанию и включали поддержку перенаправления HTTPS и HSTS.

Вызовите методы Listen или ListenUnixSocket из KestrelServerOptions, чтобы настроить префиксы URL-адресов и порты для Kestrel.

UseUrls, аргумент командной строки --urls, ключ конфигурации узла urls и переменная среды ASPNETCORE_URLS тоже работают, однако на них распространяются ограничения, указанные далее в этой статье (для конфигурации конечной точки HTTPS требуется сертификат по умолчанию).

Конфигурация KestrelServerOptions:

ConfigureEndpointDefaults(Action<ListenOptions>)

Указывает конфигурацию Action для выполнения каждой заданной конечной точки. Если вызвать ConfigureEndpointDefaults несколько раз, предыдущие элементы Action будут заменены последним элементом Action.

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.ConfigureEndpointDefaults(listenOptions =>
    {
        // Configure endpoint defaults
    });
});

Примечание

К конечным точкам, созданным путем вызова Listen перед вызовом ConfigureEndpointDefaults, не будут применяться значения по умолчанию.

ConfigureHttpsDefaults(Action<HttpsConnectionAdapterOptions>)

Указывает конфигурацию Action для выполнения каждой конечной точки HTTPS. Если вызвать ConfigureHttpsDefaults несколько раз, предыдущие элементы Action будут заменены последним элементом Action.

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.ConfigureHttpsDefaults(listenOptions =>
    {
        // certificate is an X509Certificate2
        listenOptions.ServerCertificate = certificate;
    });
});

Примечание

К конечным точкам, созданным путем вызова Listen перед вызовом ConfigureHttpsDefaults, не будут применяться значения по умолчанию.

Configure(IConfiguration)

Создает загрузчик конфигурации для настройки Kestrel, который принимает IConfiguration в качестве входных данных. Для Kestrel конфигурация должна быть ограничена разделом конфигурации.

ListenOptions.UseHttps

Настройте Kestrel для использования протокола HTTPS.

Расширения ListenOptions.UseHttps:

  • UseHttps: настройте Kestrel для использования протокола HTTPS с сертификатом по умолчанию. Создает исключение, если сертификат по умолчанию не настроен.
  • UseHttps(string fileName)
  • UseHttps(string fileName, string password)
  • UseHttps(string fileName, string password, Action<HttpsConnectionAdapterOptions> configureOptions)
  • UseHttps(StoreName storeName, string subject)
  • UseHttps(StoreName storeName, string subject, bool allowInvalid)
  • UseHttps(StoreName storeName, string subject, bool allowInvalid, StoreLocation location)
  • UseHttps(StoreName storeName, string subject, bool allowInvalid, StoreLocation location, Action<HttpsConnectionAdapterOptions> configureOptions)
  • UseHttps(X509Certificate2 serverCertificate)
  • UseHttps(X509Certificate2 serverCertificate, Action<HttpsConnectionAdapterOptions> configureOptions)
  • UseHttps(Action<HttpsConnectionAdapterOptions> configureOptions)

Параметры ListenOptions.UseHttps:

  • filename — это путь и имя файла сертификата, связанного с каталогом, где находятся файлы содержимого приложения.
  • password — это пароль для доступа к данным сертификата X.509.
  • configureOptions — это Action для настройки HttpsConnectionAdapterOptions. Возвращает ListenOptions.
  • storeName — это хранилище сертификатов, из которого выполняется загрузка сертификата.
  • subject — это имя субъекта для сертификата.
  • allowInvalid указывает, следует ли учитывать недопустимые сертификаты, например самозаверяющие сертификаты.
  • location — это расположение хранилища, из которого загружается сертификат.
  • serverCertificate — это сертификат X.509.

В рабочей среде необходимо явно настроить HTTPS. Как минимум необходимо указать сертификат по умолчанию.

Поддерживаемые конфигурации, описанные далее:

  • Отсутствие конфигурации
  • Замена сертификата по умолчанию из конфигурации
  • Изменение значений по умолчанию в коде

Отсутствие конфигурации

Kestrel ожидает передачи данных через http://localhost:5000 и https://localhost:5001 (если доступен сертификат по умолчанию).

Замена сертификата по умолчанию из конфигурации

CreateDefaultBuilder по умолчанию вызывает Configure(context.Configuration.GetSection("Kestrel")), чтобы загрузить конфигурацию Kestrel. Kestrel имеет доступ к схеме конфигурации параметров приложения HTTPS по умолчанию. Настройте несколько конечных точек, включая URL-адреса и сертификаты для использования, либо из файла на диске, либо из хранилища сертификатов.

В следующем примере appsettings.json :

  • Установите для AllowInvalid значение true, чтобы разрешить использование недопустимых сертификатов (например, самозаверяющих сертификатов).
  • Любая конечная точка HTTPS, которая не указывает сертификат (HttpsDefaultCert в следующем примере), будет использовать сертификат, определенный в разделе Certificates (Сертификаты) > Default (По умолчанию), или сертификат разработки.
{
  "Kestrel": {
    "Endpoints": {
      "Http": {
        "Url": "http://localhost:5000"
      },
      "HttpsInlineCertFile": {
        "Url": "https://localhost:5001",
        "Certificate": {
          "Path": "<path to .pfx file>",
          "Password": "<certificate password>"
        }
      },
      "HttpsInlineCertStore": {
        "Url": "https://localhost:5002",
        "Certificate": {
          "Subject": "<subject; required>",
          "Store": "<certificate store; required>",
          "Location": "<location; defaults to CurrentUser>",
          "AllowInvalid": "<true or false; defaults to false>"
        }
      },
      "HttpsDefaultCert": {
        "Url": "https://localhost:5003"
      },
      "Https": {
        "Url": "https://*:5004",
        "Certificate": {
          "Path": "<path to .pfx file>",
          "Password": "<certificate password>"
        }
      }
    },
    "Certificates": {
      "Default": {
        "Path": "<path to .pfx file>",
        "Password": "<certificate password>"
      }
    }
  }
}

Вместо использования параметров Path и Password для узла сертификата можно указать сертификат с помощью полей хранилища сертификатов. Например, сертификат из раздела Сертификаты > По умолчанию можно указать следующим образом:

"Default": {
  "Subject": "<subject; required>",
  "Store": "<cert store; required>",
  "Location": "<location; defaults to CurrentUser>",
  "AllowInvalid": "<true or false; defaults to false>"
}

Примечания к схеме.

  • Регистр букв в именах конечных точек не учитывается. Например, HTTPS и Https являются допустимыми.
  • Параметр Url является обязательным для каждой конечной точки. Формат этого параметра такой же, как для параметра конфигурации Urls верхнего уровня, только он ограничен одиночным значением.
  • Эти конечные точки заменяют конечные точки, определенные в конфигурации Urls верхнего уровня, а не дополняют их. Конечные точки, определенные в коде через Listen, объединяются с конечными точками, определенными в разделе конфигурации.
  • Раздел Certificate является необязательным. Если раздел Certificate не указан, используются значения по умолчанию, определенные в предыдущих сценариях. Если значений по умолчанию нет, сервер выдает исключение и не запускается.
  • Раздел Certificate поддерживает сертификаты PathPassword и SubjectStore.
  • Таким образом, можно определить любое количество конечных точек, если это не приводит к конфликту портов.
  • options.Configure(context.Configuration.GetSection("{SECTION}")) возвращает KestrelConfigurationLoader с методом .Endpoint(string name, listenOptions => { }), который может использоваться в качестве дополнения для параметров настроенной конечной точки:
webBuilder.UseKestrel((context, serverOptions) =>
{
    serverOptions.Configure(context.Configuration.GetSection("Kestrel"))
        .Endpoint("HTTPS", listenOptions =>
        {
            listenOptions.HttpsOptions.SslProtocols = SslProtocols.Tls12;
        });
});

Можно обратиться напрямую к KestrelServerOptions.ConfigurationLoader, чтобы и далее выполнять итерацию с существующим загрузчиком, например, предоставленным CreateDefaultBuilder.

  • Раздел конфигурации для каждой конечной точки доступен в параметрах в методе Endpoint, чтобы можно было прочитать пользовательские параметры.
  • Можно загрузить несколько конфигураций, снова вызвав options.Configure(context.Configuration.GetSection("{SECTION}")) с другим разделом. Используется только последняя конфигурация, если явным образом не вызвать Load в предыдущих экземплярах. Метапакет не вызывает Load, чтобы можно было заменить его раздел конфигурации по умолчанию.
  • KestrelConfigurationLoader отражает семейство API Listen из KestrelServerOptions как перегрузки Endpoint, чтобы можно было настроить конечные точки кода и конфигурации в одном месте. Эти перегрузки не используют имена и используют только параметры по умолчанию из конфигурации.

Изменение значений по умолчанию в коде

Можно использовать ConfigureEndpointDefaults и ConfigureHttpsDefaults для изменения параметров по умолчанию для ListenOptions и HttpsConnectionAdapterOptions, включая переопределение сертификата по умолчанию, указанного в предыдущем сценарии. Необходимо вызвать ConfigureEndpointDefaults и ConfigureHttpsDefaults, прежде чем настраивать конечные точки.

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.ConfigureEndpointDefaults(listenOptions =>
    {
        // Configure endpoint defaults
    });

    serverOptions.ConfigureHttpsDefaults(listenOptions =>
    {
        listenOptions.SslProtocols = SslProtocols.Tls12;
    });
});

Поддержка SNI в Kestrel

Можно использовать указание имени сервера (SNI) для размещения нескольких доменов в одном IP-адресе и порте. Для использования SNI клиент отправляет имя узла для безопасного сеанса серверу во время подтверждения TLS, чтобы сервер предоставил правильный сертификат. Клиент использует предоставленный сертификат для зашифрованного соединения с сервером во время безопасного сеанса, который следует после подтверждения TLS.

Kestrel поддерживает SNI через обратный вызов ServerCertificateSelector. Функция обратного вызова используется один раз за подключение, чтобы приложение проверило имя узла и выбрало соответствующий сертификат.

Поддержка SNI требует:

  • Запуск на целевой платформе netcoreapp2.1 или более поздней версии. В net461 или более поздней версии обратный вызов выполняется, но name всегда имеет значение null. name также имеет значение null, если клиент не предоставляет параметр имени узла при подтверждении TLS.
  • Все веб-сайты выполняются на одном и том же экземпляре Kestrel. Kestrel не поддерживает совместное использование IP-адреса и порта на нескольких экземплярах без обратного прокси-сервера.
webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.ListenAnyIP(5005, listenOptions =>
    {
        listenOptions.UseHttps(httpsOptions =>
        {
            var localhostCert = CertificateLoader.LoadFromStoreCert(
                "localhost", "My", StoreLocation.CurrentUser,
                allowInvalid: true);
            var exampleCert = CertificateLoader.LoadFromStoreCert(
                "example.com", "My", StoreLocation.CurrentUser,
                allowInvalid: true);
            var subExampleCert = CertificateLoader.LoadFromStoreCert(
                "sub.example.com", "My", StoreLocation.CurrentUser,
                allowInvalid: true);
            var certs = new Dictionary<string, X509Certificate2>(
                StringComparer.OrdinalIgnoreCase);
            certs["localhost"] = localhostCert;
            certs["example.com"] = exampleCert;
            certs["sub.example.com"] = subExampleCert;

            httpsOptions.ServerCertificateSelector = (connectionContext, name) =>
            {
                if (name != null && certs.TryGetValue(name, out var cert))
                {
                    return cert;
                }

                return exampleCert;
            };
        });
    });
});

Ведение журнала подключения

Вызовите UseConnectionLogging, чтобы выдать журналы уровня отладки для обмена данными на уровне байтов в рамках подключения. Ведение журнала подключения полезно для устранения неполадок, связанных с низкоуровневым взаимодействием, например при TLS-шифровании и работе за прокси-серверами. Если UseConnectionLogging поместить перед UseHttps, в журнале регистрируется зашифрованный трафик. Если UseConnectionLogging поместить после UseHttps, в журнале регистрируется расшифрованный трафик.

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.Listen(IPAddress.Any, 8000, listenOptions =>
    {
        listenOptions.UseConnectionLogging();
    });
});

Привязка к TCP-сокету

Метод Listen выполняет привязку к TCP-сокету, а лямбда-выражение параметров позволяет настроить конфигурацию сертификата X.509:

public static void Main(string[] args)
{
    CreateHostBuilder(args).Build().Run();
}

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.ConfigureKestrel(serverOptions =>
            {
                serverOptions.Listen(IPAddress.Loopback, 5000);
                serverOptions.Listen(IPAddress.Loopback, 5001, 
                    listenOptions =>
                    {
                        listenOptions.UseHttps("testCert.pfx", 
                            "testPassword");
                    });
            })
            .UseStartup<Startup>();
        });

В этом примере настраивается HTTPS для конечной точки с помощью ListenOptions. С помощью этого API можно настроить и другие параметры Kestrel для отдельных конечных точек.

В Windows самозаверяющие сертификаты создаются с помощью командлета PowerShell New-SelfSignedCertificate. Примеры, которые не поддерживаются, см. в разделе UpdateIISExpressSSLForChrome.ps1.

В macOS, Linux и Windows сертификаты создаются с помощью OpenSSL.

Привязка к сокету UNIX

Вы можете прослушивать сокет UNIX с помощью ListenUnixSocket, чтобы улучшить производительность Nginx, как показано в следующем примере:

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.ListenUnixSocket("/tmp/kestrel-test.sock");
    serverOptions.ListenUnixSocket("/tmp/kestrel-test.sock", 
        listenOptions =>
        {
            listenOptions.UseHttps("testCert.pfx", 
                "testpassword");
        });
})
  • В файле конфигурации Nginx установите для записи server > location > proxy_pass значение http://unix:/tmp/{KESTREL SOCKET}:/;. {KESTREL SOCKET} — это имя сокета, предоставленного для ListenUnixSocket (как kestrel-test.sock в предыдущем примере).
  • Убедитесь, что сокет доступен для записи Nginx (например, chmod go+w /tmp/kestrel-test.sock).

Порт 0

Если указать номер порта 0, Kestrel будет динамически привязан к доступному порту. В следующем примере показано, как определить, к какому порту фактически привязан Kestrel во время выполнения:

public void Configure(IApplicationBuilder app)
{
    var serverAddressesFeature = 
        app.ServerFeatures.Get<IServerAddressesFeature>();

    app.UseStaticFiles();

    app.Run(async (context) =>
    {
        context.Response.ContentType = "text/html";
        await context.Response
            .WriteAsync("<!DOCTYPE html><html lang=\"en\"><head>" +
                "<title></title></head><body><p>Hosted by Kestrel</p>");

        if (serverAddressesFeature != null)
        {
            await context.Response
                .WriteAsync("<p>Listening on the following addresses: " +
                    string.Join(", ", serverAddressesFeature.Addresses) +
                    "</p>");
        }

        await context.Response.WriteAsync("<p>Request URL: " +
            $"{context.Request.GetDisplayUrl()}<p>");
    });
}

Когда приложение выполняется, в выходных данных в окне консоли указывается динамический порт, по которому можно связаться с приложением:

Listening on the following addresses: http://127.0.0.1:48508

Ограничения

Настройте конечные точки с помощью следующих подходов:

  • UseUrls
  • Аргументы командной строки --urls.
  • Ключ конфигурации узла urls.
  • Переменная среды ASPNETCORE_URLS.

Эти методы удобны, если нужно, чтобы код работал с серверами, отличающимися от Kestrel. Не забывайте о следующих ограничениях.

  • С этими подходами нельзя использовать HTTPS, если в конфигурации конечной точки HTTPS не предоставлен сертификат по умолчанию (например, с помощью конфигурации KestrelServerOptions или файла конфигурации, как показано выше в этом разделе).
  • Если подходы Listen и UseUrls используются одновременно, конечные точки Listen переопределяют конечные точки UseUrls.

Конфигурация конечной точки IIS

При использовании служб IIS привязки URL-адресов для IIS переопределяют привязки, заданные Listen или UseUrls. Дополнительные сведения см. в статье Модуль ASP.NET Core.

ListenOptions.Protocols

Свойство Protocols устанавливает протоколы HTTP (HttpProtocols), разрешенные для конечной точки подключения или для сервера. Значение свойства Protocols должно входить в перечисление HttpProtocols.

Значение перечисления HttpProtocols Допустимый протокол подключения
Http1 Только HTTP/1.1. Можно использовать с протоколом TLS или без него.
Http2 Только HTTP/2. Может использоваться без TLS только в том случае, если клиент поддерживает режим предварительного знания.
Http1AndHttp2 HTTP/1.1 и HTTP/2. Для использования HTTP/2 требуется, чтобы клиент выбрал HTTP/2 при подтверждении согласования протокола уровня приложений (ALPN); в противном случае используется подключение по умолчанию HTTP/1.1.

Значение ListenOptions.Protocols по умолчанию для любой конечной точки равно HttpProtocols.Http1AndHttp2.

Ограничения TLS для HTTP/2:

  • TSL 1.2 или более поздней версии.
  • Повторное согласование отключено.
  • Сжатие отключено.
  • Минимальные размеры обмена временными ключами:
    • эллиптическая кривая Диффи—Хелмана (ECDHE) [RFC4492]: не менее 224 бит;
    • конечное поле Диффи—Хелмана (DHE) [TLS12]: не менее 2048 бит.
  • Набор шифров не запрещен.

По умолчанию поддерживается TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 [TLS-ECDHE] с эллиптической кривой P-256 [FIPS186].

Следующий пример разрешает подключения HTTP/1.1 и HTTP/2 через порт 8000. Эти подключения шифруются по протоколу TLS с использованием предоставленного сертификата:

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.Listen(IPAddress.Any, 8000, listenOptions =>
    {
        listenOptions.UseHttps("testCert.pfx", "testPassword");
    });
});

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

Следующий пример вызывает NotSupportedException для любого алгоритма шифрования, который не поддерживается приложением. Также можно определить и сравнить ITlsHandshakeFeature.CipherAlgorithm со списком приемлемых наборов шифров.

При использовании алгоритма шифрования CipherAlgorithmType.Null шифрование не используется.

// using System.Net;
// using Microsoft.AspNetCore.Connections;

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.Listen(IPAddress.Any, 8000, listenOptions =>
    {
        listenOptions.UseHttps("testCert.pfx", "testPassword");
        listenOptions.UseTlsFilter();
    });
});
using System;
using System.Security.Authentication;
using Microsoft.AspNetCore.Connections.Features;

namespace Microsoft.AspNetCore.Connections
{
    public static class TlsFilterConnectionMiddlewareExtensions
    {
        public static IConnectionBuilder UseTlsFilter(
            this IConnectionBuilder builder)
        {
            return builder.Use((connection, next) =>
            {
                var tlsFeature = connection.Features.Get<ITlsHandshakeFeature>();

                if (tlsFeature.CipherAlgorithm == CipherAlgorithmType.Null)
                {
                    throw new NotSupportedException("Prohibited cipher: " +
                        tlsFeature.CipherAlgorithm);
                }

                return next();
            });
        }
    }
}

Фильтрацию соединений также можно настроить с помощью лямбды IConnectionBuilder:

// using System;
// using System.Net;
// using System.Security.Authentication;
// using Microsoft.AspNetCore.Connections;
// using Microsoft.AspNetCore.Connections.Features;

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.Listen(IPAddress.Any, 8000, listenOptions =>
    {
        listenOptions.UseHttps("testCert.pfx", "testPassword");
        listenOptions.Use((context, next) =>
        {
            var tlsFeature = context.Features.Get<ITlsHandshakeFeature>();

            if (tlsFeature.CipherAlgorithm == CipherAlgorithmType.Null)
            {
                throw new NotSupportedException(
                    $"Prohibited cipher: {tlsFeature.CipherAlgorithm}");
            }

            return next();
        });
    });
});

В Linux для фильтрации подтверждений TLS по каждому соединению можно использовать CipherSuitesPolicy:

// using System.Net.Security;
// using Microsoft.AspNetCore.Hosting;
// using Microsoft.AspNetCore.Server.Kestrel.Core;
// using Microsoft.Extensions.DependencyInjection;
// using Microsoft.Extensions.Hosting;

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.ConfigureHttpsDefaults(listenOptions =>
    {
        listenOptions.OnAuthenticate = (context, sslOptions) =>
        {
            sslOptions.CipherSuitesPolicy = new CipherSuitesPolicy(
                new[]
                {
                    TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
                    TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
                    // ...
                });
        };
    });
});

Выбор протокола из конфигурации

CreateDefaultBuilder по умолчанию вызывает serverOptions.Configure(context.Configuration.GetSection("Kestrel")), чтобы загрузить конфигурацию Kestrel.

В следующем примере appsettings.json для всех конечных точек устанавливается протокол подключения по умолчанию HTTP/1.1:

{
  "Kestrel": {
    "EndpointDefaults": {
      "Protocols": "Http1"
    }
  }
}

В следующем примере appsettings.json для отдельной конечной точки устанавливается протокол подключения HTTP/1.1:

{
  "Kestrel": {
    "Endpoints": {
      "HttpsDefaultCert": {
        "Url": "https://localhost:5001",
        "Protocols": "Http1"
      }
    }
  }
}

Указанные в коде протоколы переопределяют значения, заданные в конфигурации.

Префиксы URL-адресов

Если вы используете UseUrls, аргумент командной строки --urls, ключ конфигурации узла urls или переменную среды ASPNETCORE_URLS, префиксы URL-адресов могут иметь любой из указанных ниже форматов.

Допустимы только префиксы URL-адресов HTTP. Kestrel не поддерживает HTTP при настройке привязок URL-адресов с помощью UseUrls.

  • IPv4-адрес с номером порта

    http://65.55.39.10:80/
    

    0.0.0.0 является особым случаем, соответствующим привязке ко всем IPv4-адресам.

  • IPv6-адрес с номером порта

    http://[0:0:0:0:0:ffff:4137:270a]:80/
    

    [::] является IPv6-аналогом IPv4-адреса 0.0.0.0.

  • Имя узла с номером порта

    http://contoso.com:80/
    http://*:80/
    

    Имена узлов, * и +, не являются особыми. Все, что не распознается как допустимый IP-адрес или localhost, привязывается ко всем IP-адресам IPv4 и IPv6. Чтобы привязать разные имена узлов к разным приложениям ASP.NET Core по одному порту, используйте HTTP.sys или обратный прокси-сервер, такой как IIS, Nginx или Apache.

    Предупреждение

    Для размещения в конфигурации обратного прокси-сервера требуется конфигурация ПО промежуточного слоя перенаправленных заголовков.

  • Имя узла localhost с номером порта или IP-адрес замыкания на себя с номером порта

    http://localhost:5000/
    http://127.0.0.1:5000/
    http://[::1]:5000/
    

    Если указать localhost, Kestrel попытается привязаться к обоим интерфейсам замыкания на себя IPv4 и IPv6. Если запрошенный порт уже используется другой службой в одном из интерфейсов замыкания на себя, Kestrel не будет запущен. Если один из интерфейсов замыкания на себя недоступен по любой другой причине (чаще всего из-за отсутствия поддержки IPv6), Kestrel зарегистрирует предупреждение.

Фильтрация узлов

Хотя Kestrel поддерживает конфигурации с использованием префиксов, например http://example.com:5000, Kestrel в основном не учитывает имя узла. Узел localhost является особым случаем, используемым для привязки к адресам замыкания на себя. Любой узел, отличный от явного IP-адреса, привязывается ко всем общедоступным IP-адресам. Заголовки Host не проверяются.

В качестве обходного решения используйте ПО промежуточного слоя фильтрации узлов. ПО промежуточного слоя фильтрации узлов предоставляется пакетом Microsoft.AspNetCore.HostFiltering, который неявно предоставляется для приложений ASP.NET Core. ПО промежуточного слоя добавляется в CreateDefaultBuilder, который вызывает AddHostFiltering:

public class Program
{
    public static void Main(string[] args)
    {
        CreateWebHostBuilder(args).Build().Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>();
}

ПО промежуточного слоя фильтрации узлов отключено по умолчанию. Чтобы включить ПО промежуточного слоя, определите ключ AllowedHosts в appsettings.json /appsettings.<EnvironmentName>.json. Значение представляет собой разделенный точками с запятой список имен узлов без номеров портов:

appsettings.json:

{
  "AllowedHosts": "example.com;localhost"
}

Примечание

ПО промежуточного слоя перенаправления заголовков имеет также параметр AllowedHosts. ПО промежуточного слоя перенаправления заголовков и ПО промежуточного слоя фильтрации узлов обладают сходными возможностями для различных сценариев. Параметр AllowedHosts с ПО промежуточного слоя перенаправления заголовков подходит для случаев, когда заголовок Host не сохраняется при переадресации запросов с помощью обратного прокси-сервера или подсистемы балансировки нагрузки. Параметр AllowedHosts с ПО промежуточного слоя фильтрации узлов применим, когда Kestrel используется в качестве общедоступного пограничного сервера или если заголовок Host пересылается напрямую.

Дополнительные сведения о ПО промежуточного слоя перенаправления заголовков см. в статье Настройка ASP.NET Core для работы с прокси-серверами и подсистемами балансировки нагрузки.

Конфигурация транспорта Libuv

Для проектов, где требуется использовать Libuv (UseLibuv):

  • Добавьте зависимость для пакета Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv в файл проекта приложения:

    <PackageReference Include="Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv"
                      Version="{VERSION}" />
    
  • Вызовите UseLibuv для IWebHostBuilder:

    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }
    
        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseLibuv();
                    webBuilder.UseStartup<Startup>();
                });
    }
    

Очистка запросов HTTP/1.1

Открытие HTTP-соединений занимает много времени. Для протокола HTTPS это также требует больших ресурсов. Поэтому Kestrel пытается повторно использовать подключения по протоколу HTTP/1.1. Чтобы разрешить повторное использование соединения, текст запроса должен быть полностью использован. Приложение не всегда использует текст запроса, например запросы POST, в которых сервер возвращает ответ перенаправления или 404. В случае перенаправления POST:

  • Возможно, клиент уже отправил часть данных POST.
  • Сервер записывает ответ 301.
  • Соединение нельзя использовать для нового запроса, пока не будут полностью прочитаны данные POST из предыдущего текста запроса.
  • Kestrel пытается очистить текст запроса. Очистка текста запроса означает чтение и отмену данных без их обработки.

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

  • Время ожидания очистки составляет 5 секунд. Этот параметр нельзя изменить.
  • Если все данные, указанные в заголовке Content-Length или Transfer-Encoding, не были считаны до истечения времени ожидания, соединение закрывается.

Иногда может потребоваться немедленно завершить запрос до или после записи ответа. Например, клиенты могут иметь ограничения на данные, поэтому ограничение передаваемых данных может иметь приоритет. В таких случаях для завершения запроса вызовите HttpContext.Abort из контроллера, страницы Razor или ПО промежуточного слоя.

Вызов Abort имеет определенные недостатки.

  • Создание новых подключений может выполняться очень медленно и требовать много ресурсов.
  • Нет никакой гарантии, что клиент прочитал ответ перед закрытием соединения.
  • Вызов Abort следует использовать редко и только для серьезных, а не распространенных ошибок.
    • Вызывайте Abort, только когда нужно решить конкретную проблему. Например, вызовите Abort, если вредоносные клиенты пытаются выполнить операцию POST с данными или если в клиентском коде есть ошибка, вызывающая большие или многочисленные запросы.
    • Не вызывайте Abort для распространенных ошибок, таких как HTTP 404 (не найдено).

Вызов HttpResponse.CompleteAsync перед вызовом Abort гарантирует, что сервер завершит запись ответа. Однако поведение клиента не предсказуемо. Он может не считать ответ, прежде чем подключение будет прервано.

Этот процесс отличается для HTTP/2, так как протокол поддерживает прерывание отдельных потоков запросов без закрытия соединения. 5-секундное время ожидания очистки не применяется. Если после завершения ответа сервер содержит непрочтенные данные текста запроса, он отправляет кадр HTTP/2 RST. Дополнительные кадры данных текста запроса игнорируются.

По возможности клиентам лучше использовать заголовок запроса Expect: 100-continue и дожидаться ответа сервера перед началом отправки текста запроса. Это дает клиенту возможность проверить ответ и прервать операцию перед отправкой ненужных данных.

Дополнительные ресурсы

Kestrel — это кроссплатформенный веб-сервер для ASP.NET Core. Kestrel — это веб-сервер, который по умолчанию включается в шаблоны проектов ASP.NET Core.

Kestrel поддерживается в следующих сценариях:

  • HTTPS
  • Непрозрачное обновление для поддержки WebSocket
  • Сокеты UNIX для повышения производительности при работе за Nginx
  • HTTP/2 (за исключением macOS†)

† HTTP/2 будет поддерживаться для macOS в будущих выпусках.

Kestrel поддерживается на всех платформах и во всех версиях, поддерживаемых .NET Core.

Просмотреть или скачать образец кода (как скачивать)

Поддержка HTTP/2

Протокол HTTP/2 доступен для приложений ASP.NET Core, если выполнены следующие базовые требования:

  • Операционная система†:
    • Windows Server 2016 / Windows 10 или более поздних версий‡
    • Linux с OpenSSL 1.0.2 или более поздней версии (например, Ubuntu 16.04 или более поздней версии).
  • Требуемая версия .NET Framework: .NET Core версии 2.2 или более поздней
  • Подключение с поддержкой согласования протокола уровня приложений (ALPN).
  • Подключение TLS 1.2 или более поздней версии.

† HTTP/2 будет поддерживаться для macOS в будущих выпусках. ‡ Kestrel имеет ограниченную поддержку HTTP/2 в Windows Server 2012 R2 и Windows 8.1. Поддержка ограничена из-за небольшого числа поддерживаемых комплектов шифров TLS, доступных для этих операционных систем. Для обеспечения безопасности TLS-подключений может потребоваться сертификат, созданный с использованием алгоритма ECDSA.

Если установлено подключение HTTP/2, HttpRequest.Protocol возвращает HTTP/2.

По умолчанию протокол HTTP/2 отключен. Дополнительные сведения о конфигурации см. в разделах, посвященных параметрам Kestrel и ListenOptions.Protocols.

Использование Kestrel с обратным прокси-сервером

Kestrel можно использовать отдельно или с обратным прокси-сервером, таким как IIS, Nginx или Apache. Обратный прокси-сервер получает HTTP-запросы из сети и пересылает их в Kestrel.

Kestrel используется в качестве пограничного (с выходом в Интернет) веб-сервера:

Kestrel взаимодействует с Интернетом напрямую без обратного прокси-сервера

Kestrel используется в конфигурации обратного прокси-сервера.

Kestrel косвенно обменивается данными с Интернетом через обратный прокси-сервер, такой как IIS, Nginx или Apache

Любая из этих конфигураций — с обратным прокси-сервером и без него — является поддерживаемой конфигурацией для размещения.

Kestrel, используемый в качестве пограничного сервера без обратного прокси-сервера, не поддерживает обращение нескольких процессов к одним и тем же IP-адресам и портам. Когда Kestrel настроен на прослушивание порта, Kestrel обрабатывает весь трафик для этого порта независимо от заголовков запросов Host. Обратный прокси-сервер, который может совместно использовать порты, также может пересылать запросы в Kestrel с уникальными IP-адресом и портом.

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

Обратный прокси-сервер:

  • Может ограничить общедоступную контактную зону размещенных на нем приложений.
  • Предоставляет дополнительный уровень конфигурации и защиты.
  • Может лучше интегрироваться с существующей инфраструктурой.
  • Упрощает настройку балансировки нагрузки и безопасных подключений (HTTPS). Сертификат X.509 требуется только обратному прокси-серверу, а сам этот сервер может обмениваться данными с серверами приложения во внутренней сети по обычному протоколу HTTP.

Предупреждение

Для размещения в конфигурации обратного прокси-сервера требуется конфигурация ПО промежуточного слоя перенаправленных заголовков.

Использование Kestrel в приложениях ASP.NET Core

Пакет Microsoft.AspNetCore.Server.Kestrel входит в состав метапакета Microsoft.AspNetCore.App.

Шаблоны проектов ASP.NET Core используют Kestrel по умолчанию. В файле Program.cs код шаблона вызывает метод CreateDefaultBuilder, который в фоновом режиме вызывает UseKestrel.

public static void Main(string[] args)
{
    CreateWebHostBuilder(args).Build().Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>();

Дополнительные сведения о CreateDefaultBuilder и построении узла, см. в разделе Настройка узла, разделы Веб-узел ASP.NET Core.

Чтобы задать дополнительную конфигурацию после вызова CreateDefaultBuilder, используйте ConfigureKestrel:

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .ConfigureKestrel((context, serverOptions) =>
        {
            // Set properties and call methods on serverOptions
        });

Если приложение не вызывает CreateDefaultBuilder, чтобы настроить узел, вызовите UseKestrel перед вызовом ConfigureKestrel:

public static void Main(string[] args)
{
    var host = new WebHostBuilder()
        .UseContentRoot(Directory.GetCurrentDirectory())
        .UseKestrel()
        .UseIISIntegration()
        .UseStartup<Startup>()
        .ConfigureKestrel((context, serverOptions) =>
        {
            // Set properties and call methods on serverOptions
        })
        .Build();

    host.Run();
}

Параметры Kestrel

Веб-сервер Kestrel имеет ограничивающие параметры конфигурации, которые удобно использовать в развертываниях с выходом в Интернет.

Задать ограничения для свойства Limits в классе KestrelServerOptions. Свойство Limits содержит экземпляр класса KestrelServerLimits.

В следующих примерах используется пространство имен Microsoft.AspNetCore.Server.Kestrel.Core.

using Microsoft.AspNetCore.Server.Kestrel.Core;

Параметры Kestrel, которые настраиваются в коде C# в следующих примерах, можно также задать с помощью поставщика конфигурации. Например, поставщик конфигурации файла может загрузить конфигурацию Kestrel из файла appsettings.json или appsettings.{Environment}.json:

{
  "Kestrel": {
    "Limits": {
      "MaxConcurrentConnections": 100,
      "MaxConcurrentUpgradedConnections": 100
    }
  }
}

Воспользуйтесь одним из перечисленных ниже подходов.

  • Настройте Kestrel в Startup.ConfigureServices:

    1. Внедрение экземпляра IConfiguration в класс Startup. В следующем примере предполагается, что введенная конфигурация назначается свойству Configuration.

    2. В Startup.ConfigureServices загрузите раздел конфигурации Kestrel в конфигурацию Kestrel:

      using Microsoft.Extensions.Configuration
      
      public class Startup
      {
          public Startup(IConfiguration configuration)
          {
              Configuration = configuration;
          }
      
          public IConfiguration Configuration { get; }
      
          public void ConfigureServices(IServiceCollection services)
          {
              services.Configure<KestrelServerOptions>(
                  Configuration.GetSection("Kestrel"));
          }
      
          public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
          {
              ...
          }
      }
      
  • Настройте Kestrel при создании узла:

    В Program.cs загрузите раздел конфигурации Kestrel в конфигурацию Kestrel.

    // using Microsoft.Extensions.DependencyInjection;
    
    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .ConfigureServices((context, services) =>
            {
                services.Configure<KestrelServerOptions>(
                    context.Configuration.GetSection("Kestrel"));
            })
            .UseStartup<Startup>();
    

Оба предыдущих подхода работают с любым поставщиком конфигурации.

Время ожидания проверки на активность

KeepAliveTimeout

Получает или задает время ожидания проверки на активность. Значение по умолчанию — 2 минуты.

.ConfigureKestrel((context, serverOptions) =>
{
    serverOptions.Limits.MaxConcurrentConnections = 100;
    serverOptions.Limits.MaxConcurrentUpgradedConnections = 100;
    serverOptions.Limits.MaxRequestBodySize = 10 * 1024;
    serverOptions.Limits.MinRequestBodyDataRate =
        new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    serverOptions.Limits.MinResponseDataRate =
        new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    serverOptions.Listen(IPAddress.Loopback, 5000);
    serverOptions.Listen(IPAddress.Loopback, 5001, listenOptions =>
    {
        listenOptions.UseHttps("testCert.pfx", "testPassword");
    });
    serverOptions.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(2);
    serverOptions.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(1);
});

максимальное число клиентских подключений;

MaxConcurrentConnections MaxConcurrentUpgradedConnections

Максимальное число одновременно открытых подключений TCP для всего приложения можно задать с помощью следующего кода:

.ConfigureKestrel((context, serverOptions) =>
{
    serverOptions.Limits.MaxConcurrentConnections = 100;
    serverOptions.Limits.MaxConcurrentUpgradedConnections = 100;
    serverOptions.Limits.MaxRequestBodySize = 10 * 1024;
    serverOptions.Limits.MinRequestBodyDataRate =
        new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    serverOptions.Limits.MinResponseDataRate =
        new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    serverOptions.Listen(IPAddress.Loopback, 5000);
    serverOptions.Listen(IPAddress.Loopback, 5001, listenOptions =>
    {
        listenOptions.UseHttps("testCert.pfx", "testPassword");
    });
    serverOptions.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(2);
    serverOptions.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(1);
});

Существует отдельный предел по подключениям, измененным с HTTP или HTTPS на другой протокол (например, по запросу WebSocket). После изменения подключение не учитывается в пределе MaxConcurrentConnections.

.ConfigureKestrel((context, serverOptions) =>
{
    serverOptions.Limits.MaxConcurrentConnections = 100;
    serverOptions.Limits.MaxConcurrentUpgradedConnections = 100;
    serverOptions.Limits.MaxRequestBodySize = 10 * 1024;
    serverOptions.Limits.MinRequestBodyDataRate =
        new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    serverOptions.Limits.MinResponseDataRate =
        new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    serverOptions.Listen(IPAddress.Loopback, 5000);
    serverOptions.Listen(IPAddress.Loopback, 5001, listenOptions =>
    {
        listenOptions.UseHttps("testCert.pfx", "testPassword");
    });
    serverOptions.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(2);
    serverOptions.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(1);
});

По умолчанию максимальное число подключений не ограничено (null).

максимальный размер текста запроса;

MaxRequestBodySize

По умолчанию максимальный размер текста запроса составляет 30 000 000 байт, что примерно соответствует 28,6 МБ.

Чтобы переопределить это ограничение в приложении MVC ASP.NET Core, мы рекомендуем использовать атрибут RequestSizeLimitAttribute в методе действия:

[RequestSizeLimit(100000000)]
public IActionResult MyActionMethod()

Приведенный ниже пример показывает, как настроить ограничение для приложения и каждого запроса:

.ConfigureKestrel((context, serverOptions) =>
{
    serverOptions.Limits.MaxConcurrentConnections = 100;
    serverOptions.Limits.MaxConcurrentUpgradedConnections = 100;
    serverOptions.Limits.MaxRequestBodySize = 10 * 1024;
    serverOptions.Limits.MinRequestBodyDataRate =
        new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    serverOptions.Limits.MinResponseDataRate =
        new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    serverOptions.Listen(IPAddress.Loopback, 5000);
    serverOptions.Listen(IPAddress.Loopback, 5001, listenOptions =>
    {
        listenOptions.UseHttps("testCert.pfx", "testPassword");
    });
    serverOptions.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(2);
    serverOptions.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(1);
});

Переопределите параметр для конкретного запроса в ПО промежуточного слоя:

app.Run(async (context) =>
{
    context.Features.Get<IHttpMaxRequestBodySizeFeature>()
        .MaxRequestBodySize = 10 * 1024;

    var minRequestRateFeature = 
        context.Features.Get<IHttpMinRequestBodyDataRateFeature>();
    var minResponseRateFeature = 
        context.Features.Get<IHttpMinResponseDataRateFeature>();

    if (minRequestRateFeature != null)
    {
        minRequestRateFeature.MinDataRate = new MinDataRate(
            bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    }

    if (minResponseRateFeature != null)
    {
        minResponseRateFeature.MinDataRate = new MinDataRate(
            bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    }

Если приложение пытается настроить ограничение для запроса после того, как оно начало считывать запрос, возникает исключение. Доступно свойство IsReadOnly, указывающее, что свойство MaxRequestBodySize находится в состоянии только для чтения и настраивать ограничение слишком поздно.

При запуске приложения вне процесса, который обслуживает модуль ASP.NET Core, ограничение на размер текста запроса Kestrel будет отключено, так как оно уже задается IIS.

минимальная скорость передачи данных в тексте запроса.

MinRequestBodyDataRate MinResponseDataRate

Kestrel каждую секунду проверяет, поступают ли данные с указанной скоростью в байтах в секунду. Если скорость падает ниже минимума, для подключения истекает время ожидания. Льготный период — это время, которое Kestrel предоставляет клиенту для увеличения скорости отправки до минимального уровня; в течение этого периода скорость не проверяется. Льготный период помогает избежать разрыва соединений, которые первоначально отправляют данные с небольшой скоростью из-за медленного запуска TCP.

Минимальная скорость по умолчанию составляет 240 байт/с, льготный период равен 5 секундам.

Минимальная скорость также применяется к отклику. Код для задания лимита запросов и лимита откликов различается только наличием RequestBody или Response в именах свойств и интерфейсов.

Ниже приведен пример, показывающий, как настроить минимальную скорость передачи данных в Program.cs:

.ConfigureKestrel((context, serverOptions) =>
{
    serverOptions.Limits.MaxConcurrentConnections = 100;
    serverOptions.Limits.MaxConcurrentUpgradedConnections = 100;
    serverOptions.Limits.MaxRequestBodySize = 10 * 1024;
    serverOptions.Limits.MinRequestBodyDataRate =
        new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    serverOptions.Limits.MinResponseDataRate =
        new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    serverOptions.Listen(IPAddress.Loopback, 5000);
    serverOptions.Listen(IPAddress.Loopback, 5001, listenOptions =>
    {
        listenOptions.UseHttps("testCert.pfx", "testPassword");
    });
    serverOptions.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(2);
    serverOptions.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(1);
});

Переопределите ограничения минимальной скорости для каждого запроса в ПО промежуточного слоя:

app.Run(async (context) =>
{
    context.Features.Get<IHttpMaxRequestBodySizeFeature>()
        .MaxRequestBodySize = 10 * 1024;

    var minRequestRateFeature = 
        context.Features.Get<IHttpMinRequestBodyDataRateFeature>();
    var minResponseRateFeature = 
        context.Features.Get<IHttpMinResponseDataRateFeature>();

    if (minRequestRateFeature != null)
    {
        minRequestRateFeature.MinDataRate = new MinDataRate(
            bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    }

    if (minResponseRateFeature != null)
    {
        minResponseRateFeature.MinDataRate = new MinDataRate(
            bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    }

В HttpContext.Features для запросов HTTP/2 отсутствуют возможности настройки скорости, указанные в предыдущем примере, так как изменение ограничений скорости для каждого запроса не поддерживается для HTTP/2 из-за поддержки протокола мультиплексирования запроса. Ограничения скорости на уровне сервера, которые настроены с помощью KestrelServerOptions.Limits, по-прежнему применяются к подключениям HTTP/1.x и HTTP/2.

Время ожидания для заголовков запросов

RequestHeadersTimeout

Получает или задает максимальное время, которое сервер уделяет получению заголовков запросов. Значение по умолчанию — 30 секунд.

.ConfigureKestrel((context, serverOptions) =>
{
    serverOptions.Limits.MaxConcurrentConnections = 100;
    serverOptions.Limits.MaxConcurrentUpgradedConnections = 100;
    serverOptions.Limits.MaxRequestBodySize = 10 * 1024;
    serverOptions.Limits.MinRequestBodyDataRate =
        new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    serverOptions.Limits.MinResponseDataRate =
        new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    serverOptions.Listen(IPAddress.Loopback, 5000);
    serverOptions.Listen(IPAddress.Loopback, 5001, listenOptions =>
    {
        listenOptions.UseHttps("testCert.pfx", "testPassword");
    });
    serverOptions.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(2);
    serverOptions.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(1);
});

Максимальное число потоков на подключение

Http2.MaxStreamsPerConnection ограничивает количество параллельных потоков запросов для одного соединения HTTP/2. Потоки сверх этого числа будут отклонены.

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .ConfigureKestrel((context, serverOptions) =>
        {
            serverOptions.Limits.Http2.MaxStreamsPerConnection = 100;
        });

Значение по умолчанию — 100.

Размер таблицы заголовка

Декодер HPACK распаковывает заголовки HTTP для подключений HTTP/2. Http2.HeaderTableSize ограничивает размер таблицы сжатия заголовка, которую использует декодер HPACK. Это значение указывается в октетах и должно быть больше нуля (0).

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .ConfigureKestrel((context, serverOptions) =>
        {
            serverOptions.Limits.Http2.HeaderTableSize = 4096;
        });

Значение по умолчанию — 4096.

Максимальный размер кадра

Http2.MaxFrameSize указывает максимальный размер полезных данных в получаемом кадре подключения HTTP/2. Это значение указывается в октетах и должно находиться в пределах от 2^14 (16 384) до 2^24-1 (16 777 215).

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .ConfigureKestrel((context, serverOptions) =>
        {
            serverOptions.Limits.Http2.MaxFrameSize = 16384;
        });

Значение по умолчанию — 2^14 (16 384).

Максимальный размер запроса заголовка

Http2.MaxRequestHeaderFieldSize указывает максимально допустимый размер значений заголовка запроса (в октетах). Это ограничение применяется к имени и значению в их сжатых и несжатых представлениях. Значение должно быть больше нуля.

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .ConfigureKestrel((context, serverOptions) =>
        {
            serverOptions.Limits.Http2.MaxRequestHeaderFieldSize = 8192;
        });

Значение по умолчанию — 8 192.

Размер окна начального подключения

Http2.InitialConnectionWindowSize указывает максимальное значение данных тела запроса (в байтах), буферизируемое сервером за один раз, для всех запросов (потоков) на каждое соединение. Размеры запросов также ограничиваются параметром Http2.InitialStreamWindowSize. Значение должно быть больше или равно 65 535 и меньше 2^31 (2 147 483 648).

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .ConfigureKestrel((context, serverOptions) =>
        {
            serverOptions.Limits.Http2.InitialConnectionWindowSize = 131072;
        });

Значение по умолчанию — 128 КБ (131 072).

Размер окна начального потока

Http2.InitialStreamWindowSize указывает максимальное значение данных тела запроса (в байтах), буферизируемое сервером за один раз, для каждого запроса (потока). Размеры запросов также ограничиваются параметром Http2.InitialStreamWindowSize. Значение должно быть больше или равно 65 535 и меньше 2^31 (2 147 483 648).

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .ConfigureKestrel((context, serverOptions) =>
        {
            serverOptions.Limits.Http2.InitialStreamWindowSize = 98304;
        });

Значение по умолчанию — 96 КБ (98 304).

Синхронный ввод-вывод

AllowSynchronousIO определяет, разрешены ли синхронные операции ввода-вывода для запроса и ответа. Значение по умолчанию — true.

Предупреждение

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

В примере ниже включаются синхронные операции ввода-вывода:

.ConfigureKestrel((context, serverOptions) =>
{
    serverOptions.AllowSynchronousIO = true;
});

Сведения о других параметрах и ограничениях Kestrel см. в следующих разделах:

Конфигурация конечной точки

По умолчанию платформа ASP.NET Core привязана к:

  • http://localhost:5000
  • https://localhost:5001 (если присутствует локальный сертификат разработки)

Укажите URL-адреса с помощью следующих параметров:

  • Переменная среды ASPNETCORE_URLS.
  • Аргументы командной строки --urls.
  • Ключ конфигурации узла urls.
  • Метод расширения UseUrls.

Значение, указанное с помощью этих подходов, может быть одной или несколькими конечными точками HTTP и HTTPS (HTTPS при наличии сертификата по умолчанию). Настройте значение в виде списка с разделением точкой с запятой (например, "Urls": "http://localhost:8000;http://localhost:8001").

Дополнительные сведения о таких подходах см. в разделах URL-адреса сервера и Переопределение конфигурации.

Сертификат разработки создается, когда:

В некоторых браузерах требуется явное разрешение доверять локальному сертификату разработки.

Шаблоны проектов настраивают приложения так, чтобы они запускались на базе HTTPS по умолчанию и включали поддержку перенаправления HTTPS и HSTS.

Вызовите методы Listen или ListenUnixSocket из KestrelServerOptions, чтобы настроить префиксы URL-адресов и порты для Kestrel.

UseUrls, аргумент командной строки --urls, ключ конфигурации узла urls и переменная среды ASPNETCORE_URLS тоже работают, однако на них распространяются ограничения, указанные далее в этой статье (для конфигурации конечной точки HTTPS требуется сертификат по умолчанию).

Конфигурация KestrelServerOptions:

ConfigureEndpointDefaults(Action<ListenOptions>)

Указывает конфигурацию Action для выполнения каждой заданной конечной точки. Если вызвать ConfigureEndpointDefaults несколько раз, предыдущие элементы Action будут заменены последним элементом Action.

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .ConfigureKestrel((context, serverOptions) =>
        {
            serverOptions.ConfigureEndpointDefaults(listenOptions =>
            {
                // Configure endpoint defaults
            });
        });

Примечание

К конечным точкам, созданным путем вызова Listen перед вызовом ConfigureEndpointDefaults, не будут применяться значения по умолчанию.

ConfigureHttpsDefaults(Action<HttpsConnectionAdapterOptions>)

Указывает конфигурацию Action для выполнения каждой конечной точки HTTPS. Если вызвать ConfigureHttpsDefaults несколько раз, предыдущие элементы Action будут заменены последним элементом Action.

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .ConfigureKestrel((context, serverOptions) =>
        {
            serverOptions.ConfigureHttpsDefaults(listenOptions =>
            {
                // certificate is an X509Certificate2
                listenOptions.ServerCertificate = certificate;
            });
        });

Примечание

К конечным точкам, созданным путем вызова Listen перед вызовом ConfigureHttpsDefaults, не будут применяться значения по умолчанию.

Configure(IConfiguration)

Создает загрузчик конфигурации для настройки Kestrel, который принимает IConfiguration в качестве входных данных. Для Kestrel конфигурация должна быть ограничена разделом конфигурации.

ListenOptions.UseHttps

Настройте Kestrel для использования протокола HTTPS.

Расширения ListenOptions.UseHttps:

  • UseHttps: настройте Kestrel для использования протокола HTTPS с сертификатом по умолчанию. Создает исключение, если сертификат по умолчанию не настроен.
  • UseHttps(string fileName)
  • UseHttps(string fileName, string password)
  • UseHttps(string fileName, string password, Action<HttpsConnectionAdapterOptions> configureOptions)
  • UseHttps(StoreName storeName, string subject)
  • UseHttps(StoreName storeName, string subject, bool allowInvalid)
  • UseHttps(StoreName storeName, string subject, bool allowInvalid, StoreLocation location)
  • UseHttps(StoreName storeName, string subject, bool allowInvalid, StoreLocation location, Action<HttpsConnectionAdapterOptions> configureOptions)
  • UseHttps(X509Certificate2 serverCertificate)
  • UseHttps(X509Certificate2 serverCertificate, Action<HttpsConnectionAdapterOptions> configureOptions)
  • UseHttps(Action<HttpsConnectionAdapterOptions> configureOptions)

Параметры ListenOptions.UseHttps:

  • filename — это путь и имя файла сертификата, связанного с каталогом, где находятся файлы содержимого приложения.
  • password — это пароль для доступа к данным сертификата X.509.
  • configureOptions — это Action для настройки HttpsConnectionAdapterOptions. Возвращает ListenOptions.
  • storeName — это хранилище сертификатов, из которого выполняется загрузка сертификата.
  • subject — это имя субъекта для сертификата.
  • allowInvalid указывает, следует ли учитывать недопустимые сертификаты, например самозаверяющие сертификаты.
  • location — это расположение хранилища, из которого загружается сертификат.
  • serverCertificate — это сертификат X.509.

В рабочей среде необходимо явно настроить HTTPS. Как минимум необходимо указать сертификат по умолчанию.

Поддерживаемые конфигурации, описанные далее:

  • Отсутствие конфигурации
  • Замена сертификата по умолчанию из конфигурации
  • Изменение значений по умолчанию в коде

Отсутствие конфигурации

Kestrel ожидает передачи данных через http://localhost:5000 и https://localhost:5001 (если доступен сертификат по умолчанию).

Замена сертификата по умолчанию из конфигурации

CreateDefaultBuilder по умолчанию вызывает Configure(context.Configuration.GetSection("Kestrel")), чтобы загрузить конфигурацию Kestrel. Kestrel имеет доступ к схеме конфигурации параметров приложения HTTPS по умолчанию. Настройте несколько конечных точек, включая URL-адреса и сертификаты для использования, либо из файла на диске, либо из хранилища сертификатов.

В следующем примере appsettings.json :

  • Установите для AllowInvalid значение true, чтобы разрешить использование недопустимых сертификатов (например, самозаверяющих сертификатов).
  • Любая конечная точка HTTPS, которая не указывает сертификат (HttpsDefaultCert в следующем примере), будет использовать сертификат, определенный в разделе Certificates (Сертификаты) > Default (По умолчанию), или сертификат разработки.
{
  "Kestrel": {
    "Endpoints": {
      "Http": {
        "Url": "http://localhost:5000"
      },

      "HttpsInlineCertFile": {
        "Url": "https://localhost:5001",
        "Certificate": {
          "Path": "<path to .pfx file>",
          "Password": "<certificate password>"
        }
      },

      "HttpsInlineCertStore": {
        "Url": "https://localhost:5002",
        "Certificate": {
          "Subject": "<subject; required>",
          "Store": "<certificate store; required>",
          "Location": "<location; defaults to CurrentUser>",
          "AllowInvalid": "<true or false; defaults to false>"
        }
      },

      "HttpsDefaultCert": {
        "Url": "https://localhost:5003"
      },

      "Https": {
        "Url": "https://*:5004",
        "Certificate": {
          "Path": "<path to .pfx file>",
          "Password": "<certificate password>"
        }
      }
    },
    "Certificates": {
      "Default": {
        "Path": "<path to .pfx file>",
        "Password": "<certificate password>"
      }
    }
  }
}

Вместо использования параметров Path и Password для узла сертификата можно указать сертификат с помощью полей хранилища сертификатов. Например, сертификат из раздела Сертификаты > По умолчанию можно указать следующим образом:

"Default": {
  "Subject": "<subject; required>",
  "Store": "<cert store; required>",
  "Location": "<location; defaults to CurrentUser>",
  "AllowInvalid": "<true or false; defaults to false>"
}

Примечания к схеме.

  • Регистр букв в именах конечных точек не учитывается. Например, HTTPS и Https являются допустимыми.
  • Параметр Url является обязательным для каждой конечной точки. Формат этого параметра такой же, как для параметра конфигурации Urls верхнего уровня, только он ограничен одиночным значением.
  • Эти конечные точки заменяют конечные точки, определенные в конфигурации Urls верхнего уровня, а не дополняют их. Конечные точки, определенные в коде через Listen, объединяются с конечными точками, определенными в разделе конфигурации.
  • Раздел Certificate является необязательным. Если раздел Certificate не указан, используются значения по умолчанию, определенные в предыдущих сценариях. Если значений по умолчанию нет, сервер выдает исключение и не запускается.
  • Раздел Certificate поддерживает сертификаты PathPassword и SubjectStore.
  • Таким образом, можно определить любое количество конечных точек, если это не приводит к конфликту портов.
  • options.Configure(context.Configuration.GetSection("{SECTION}")) возвращает KestrelConfigurationLoader с методом .Endpoint(string name, listenOptions => { }), который может использоваться в качестве дополнения для параметров настроенной конечной точки:
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .UseKestrel((context, serverOptions) =>
        {
            serverOptions.Configure(context.Configuration.GetSection("Kestrel"))
                .Endpoint("HTTPS", listenOptions =>
                {
                    listenOptions.HttpsOptions.SslProtocols = SslProtocols.Tls12;
                });
        });

Можно обратиться напрямую к KestrelServerOptions.ConfigurationLoader, чтобы и далее выполнять итерацию с существующим загрузчиком, например, предоставленным CreateDefaultBuilder.

  • Раздел конфигурации для каждой конечной точки доступен в параметрах в методе Endpoint, чтобы можно было прочитать пользовательские параметры.
  • Можно загрузить несколько конфигураций, снова вызвав options.Configure(context.Configuration.GetSection("{SECTION}")) с другим разделом. Используется только последняя конфигурация, если явным образом не вызвать Load в предыдущих экземплярах. Метапакет не вызывает Load, чтобы можно было заменить его раздел конфигурации по умолчанию.
  • KestrelConfigurationLoader отражает семейство API Listen из KestrelServerOptions как перегрузки Endpoint, чтобы можно было настроить конечные точки кода и конфигурации в одном месте. Эти перегрузки не используют имена и используют только параметры по умолчанию из конфигурации.

Изменение значений по умолчанию в коде

Можно использовать ConfigureEndpointDefaults и ConfigureHttpsDefaults для изменения параметров по умолчанию для ListenOptions и HttpsConnectionAdapterOptions, включая переопределение сертификата по умолчанию, указанного в предыдущем сценарии. Необходимо вызвать ConfigureEndpointDefaults и ConfigureHttpsDefaults, прежде чем настраивать конечные точки.

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .UseKestrel((context, serverOptions) =>
        {
            serverOptions.ConfigureEndpointDefaults(listenOptions =>
            {
                // Configure endpoint defaults
            });

            serverOptions.ConfigureHttpsDefaults(listenOptions =>
            {
                listenOptions.SslProtocols = SslProtocols.Tls12;
            });
        });

Поддержка SNI в Kestrel

Можно использовать указание имени сервера (SNI) для размещения нескольких доменов в одном IP-адресе и порте. Для использования SNI клиент отправляет имя узла для безопасного сеанса серверу во время подтверждения TLS, чтобы сервер предоставил правильный сертификат. Клиент использует предоставленный сертификат для зашифрованного соединения с сервером во время безопасного сеанса, который следует после подтверждения TLS.

Kestrel поддерживает SNI через обратный вызов ServerCertificateSelector. Функция обратного вызова используется один раз за подключение, чтобы приложение проверило имя узла и выбрало соответствующий сертификат.

Поддержка SNI требует:

  • Запуск на целевой платформе netcoreapp2.1 или более поздней версии. В net461 или более поздней версии обратный вызов выполняется, но name всегда имеет значение null. name также имеет значение null, если клиент не предоставляет параметр имени узла при подтверждении TLS.
  • Все веб-сайты выполняются на одном и том же экземпляре Kestrel. Kestrel не поддерживает совместное использование IP-адреса и порта на нескольких экземплярах без обратного прокси-сервера.
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .ConfigureKestrel((context, serverOptions) =>
        {
            serverOptions.ListenAnyIP(5005, listenOptions =>
            {
                listenOptions.UseHttps(httpsOptions =>
                {
                    var localhostCert = CertificateLoader.LoadFromStoreCert(
                        "localhost", "My", StoreLocation.CurrentUser,
                        allowInvalid: true);
                    var exampleCert = CertificateLoader.LoadFromStoreCert(
                        "example.com", "My", StoreLocation.CurrentUser,
                        allowInvalid: true);
                    var subExampleCert = CertificateLoader.LoadFromStoreCert(
                        "sub.example.com", "My", StoreLocation.CurrentUser,
                        allowInvalid: true);
                    var certs = new Dictionary<string, X509Certificate2>(
                        StringComparer.OrdinalIgnoreCase);
                    certs["localhost"] = localhostCert;
                    certs["example.com"] = exampleCert;
                    certs["sub.example.com"] = subExampleCert;

                    httpsOptions.ServerCertificateSelector = (connectionContext, name) =>
                    {
                        if (name != null && certs.TryGetValue(name, out var cert))
                        {
                            return cert;
                        }

                        return exampleCert;
                    };
                });
            });
        });

Ведение журнала подключения

Вызовите UseConnectionLogging, чтобы выдать журналы уровня отладки для обмена данными на уровне байтов в рамках подключения. Ведение журнала подключения полезно для устранения неполадок, связанных с низкоуровневым взаимодействием, например при TLS-шифровании и работе за прокси-серверами. Если UseConnectionLogging поместить перед UseHttps, в журнале регистрируется зашифрованный трафик. Если UseConnectionLogging поместить после UseHttps, в журнале регистрируется расшифрованный трафик.

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.Listen(IPAddress.Any, 8000, listenOptions =>
    {
        listenOptions.UseConnectionLogging();
    });
});

Привязка к TCP-сокету

Метод Listen выполняет привязку к TCP-сокету, а лямбда-выражение параметров позволяет настроить конфигурацию сертификата X.509:

public static void Main(string[] args)
{
    CreateWebHostBuilder(args).Build().Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .ConfigureKestrel((context, serverOptions) =>
        {
            serverOptions.Listen(IPAddress.Loopback, 5000);
            serverOptions.Listen(IPAddress.Loopback, 5001, listenOptions =>
            {
                listenOptions.UseHttps("testCert.pfx", "testPassword");
            });
        });

В этом примере настраивается HTTPS для конечной точки с помощью ListenOptions. С помощью этого API можно настроить и другие параметры Kestrel для отдельных конечных точек.

В Windows самозаверяющие сертификаты создаются с помощью командлета PowerShell New-SelfSignedCertificate. Примеры, которые не поддерживаются, см. в разделе UpdateIISExpressSSLForChrome.ps1.

В macOS, Linux и Windows сертификаты создаются с помощью OpenSSL.

Привязка к сокету UNIX

Вы можете прослушивать сокет UNIX с помощью ListenUnixSocket, чтобы улучшить производительность Nginx, как показано в следующем примере:

.ConfigureKestrel((context, serverOptions) =>
{
    serverOptions.ListenUnixSocket("/tmp/kestrel-test.sock");
    serverOptions.ListenUnixSocket("/tmp/kestrel-test.sock", listenOptions =>
    {
        listenOptions.UseHttps("testCert.pfx", "testpassword");
    });
});
  • В файле конфигурации Nginx установите для записи server > location > proxy_pass значение http://unix:/tmp/{KESTREL SOCKET}:/;. {KESTREL SOCKET} — это имя сокета, предоставленного для ListenUnixSocket (как kestrel-test.sock в предыдущем примере).
  • Убедитесь, что сокет доступен для записи Nginx (например, chmod go+w /tmp/kestrel-test.sock).

Порт 0

Если указать номер порта 0, Kestrel будет динамически привязан к доступному порту. В следующем примере показано, как определить, к какому порту фактически привязан Kestrel во время выполнения:

public void Configure(IApplicationBuilder app)
{
    var serverAddressesFeature = 
        app.ServerFeatures.Get<IServerAddressesFeature>();

    app.UseStaticFiles();

    app.Run(async (context) =>
    {
        context.Response.ContentType = "text/html";
        await context.Response
            .WriteAsync("<!DOCTYPE html><html lang=\"en\"><head>" +
                "<title></title></head><body><p>Hosted by Kestrel</p>");

        if (serverAddressesFeature != null)
        {
            await context.Response
                .WriteAsync("<p>Listening on the following addresses: " +
                    string.Join(", ", serverAddressesFeature.Addresses) +
                    "</p>");
        }

        await context.Response.WriteAsync("<p>Request URL: " +
            $"{context.Request.GetDisplayUrl()}<p>");
    });
}

Когда приложение выполняется, в выходных данных в окне консоли указывается динамический порт, по которому можно связаться с приложением:

Listening on the following addresses: http://127.0.0.1:48508

Ограничения

Настройте конечные точки с помощью следующих подходов:

  • UseUrls
  • Аргументы командной строки --urls.
  • Ключ конфигурации узла urls.
  • Переменная среды ASPNETCORE_URLS.

Эти методы удобны, если нужно, чтобы код работал с серверами, отличающимися от Kestrel. Не забывайте о следующих ограничениях.

  • С этими подходами нельзя использовать HTTPS, если в конфигурации конечной точки HTTPS не предоставлен сертификат по умолчанию (например, с помощью конфигурации KestrelServerOptions или файла конфигурации, как показано выше в этом разделе).
  • Если подходы Listen и UseUrls используются одновременно, конечные точки Listen переопределяют конечные точки UseUrls.

Конфигурация конечной точки IIS

При использовании служб IIS привязки URL-адресов для IIS переопределяют привязки, заданные Listen или UseUrls. Дополнительные сведения см. в статье Модуль ASP.NET Core.

ListenOptions.Protocols

Свойство Protocols устанавливает протоколы HTTP (HttpProtocols), разрешенные для конечной точки подключения или для сервера. Значение свойства Protocols должно входить в перечисление HttpProtocols.

Значение перечисления HttpProtocols Допустимый протокол подключения
Http1 Только HTTP/1.1. Можно использовать с протоколом TLS или без него.
Http2 Только HTTP/2. Может использоваться без TLS только в том случае, если клиент поддерживает режим предварительного знания.
Http1AndHttp2 HTTP/1.1 и HTTP/2. Для использования HTTP/2 требуется протокол TLS и подключение с согласованием протокола уровня приложений (ALPN); при их отсутствии используется подключение по умолчанию HTTP/1.1.

По умолчанию используется протокол HTTP/1.1.

Ограничения TLS для HTTP/2:

  • TSL 1.2 или более поздней версии.
  • Повторное согласование отключено.
  • Сжатие отключено.
  • Минимальные размеры обмена временными ключами:
    • эллиптическая кривая Диффи—Хелмана (ECDHE) [RFC4492]: не менее 224 бит;
    • конечное поле Диффи—Хелмана (DHE) [TLS12]: не менее 2048 бит.
  • Набор шифров не блокируется

По умолчанию поддерживается TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 [TLS-ECDHE] с эллиптической кривой P-256 [FIPS186].

Следующий пример разрешает подключения HTTP/1.1 и HTTP/2 через порт 8000. Эти подключения шифруются по протоколу TLS с использованием предоставленного сертификата:

.ConfigureKestrel((context, serverOptions) =>
{
    serverOptions.Listen(IPAddress.Any, 8000, listenOptions =>
    {
        listenOptions.Protocols = HttpProtocols.Http1AndHttp2;
        listenOptions.UseHttps("testCert.pfx", "testPassword");
    });
});

Также вы можете создать реализацию IConnectionAdapter для фильтрации подтверждений TLS для каждого соединения по конкретным шифрам:

.ConfigureKestrel((context, serverOptions) =>
{
    serverOptions.Listen(IPAddress.Any, 8000, listenOptions =>
    {
        listenOptions.Protocols = HttpProtocols.Http1AndHttp2;
        listenOptions.UseHttps("testCert.pfx", "testPassword");
        listenOptions.ConnectionAdapters.Add(new TlsFilterAdapter());
    });
});
private class TlsFilterAdapter : IConnectionAdapter
{
    public bool IsHttps => false;

    public Task<IAdaptedConnection> OnConnectionAsync(ConnectionAdapterContext context)
    {
        var tlsFeature = context.Features.Get<ITlsHandshakeFeature>();

        // Throw NotSupportedException for any cipher algorithm that the app doesn't
        // wish to support. Alternatively, define and compare
        // ITlsHandshakeFeature.CipherAlgorithm to a list of acceptable cipher
        // suites.
        //
        // No encryption is used with a CipherAlgorithmType.Null cipher algorithm.
        if (tlsFeature.CipherAlgorithm == CipherAlgorithmType.Null)
        {
            throw new NotSupportedException("Prohibited cipher: " + tlsFeature.CipherAlgorithm);
        }

        return Task.FromResult<IAdaptedConnection>(new AdaptedConnection(context.ConnectionStream));
    }

    private class AdaptedConnection : IAdaptedConnection
    {
        public AdaptedConnection(Stream adaptedStream)
        {
            ConnectionStream = adaptedStream;
        }

        public Stream ConnectionStream { get; }

        public void Dispose()
        {
        }
    }
}

Выбор протокола из конфигурации

CreateDefaultBuilder по умолчанию вызывает serverOptions.Configure(context.Configuration.GetSection("Kestrel")), чтобы загрузить конфигурацию Kestrel.

В следующем примере appsettings.json для всех конечных точек Kestrel устанавливается протокол подключения по умолчанию (HTTP/1.1 и HTTP/2):

{
  "Kestrel": {
    "EndpointDefaults": {
      "Protocols": "Http1AndHttp2"
    }
  }
}

В следующем примере файла конфигурации задается протокол соединения для конкретной конечной точки:

{
  "Kestrel": {
    "Endpoints": {
      "HttpsDefaultCert": {
        "Url": "https://localhost:5001",
        "Protocols": "Http1AndHttp2"
      }
    }
  }
}

Указанные в коде протоколы переопределяют значения, заданные в конфигурации.

Конфигурация транспорта Libuv

После выпуска ASP.NET Core 2.1 транспорт Kestrel по умолчанию основан не на Libuv, а на управляемых сокетах. Это критическое изменение для приложений ASP.NET Core 2.0, которые обновляются до версии 2.1, если они вызывают UseLibuv и зависят от одного из следующих пакетов:

Для проектов, где требуется использовать Libuv:

  • Добавьте зависимость для пакета Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv в файл проекта приложения:

    <PackageReference Include="Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv"
                      Version="{VERSION}" />
    
  • Вызов UseLibuv:

    public class Program
    {
        public static void Main(string[] args)
        {
            CreateWebHostBuilder(args).Build().Run();
        }
    
        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseLibuv()
                .UseStartup<Startup>();
    }
    

Префиксы URL-адресов

Если вы используете UseUrls, аргумент командной строки --urls, ключ конфигурации узла urls или переменную среды ASPNETCORE_URLS, префиксы URL-адресов могут иметь любой из указанных ниже форматов.

Допустимы только префиксы URL-адресов HTTP. Kestrel не поддерживает HTTP при настройке привязок URL-адресов с помощью UseUrls.

  • IPv4-адрес с номером порта

    http://65.55.39.10:80/
    

    0.0.0.0 является особым случаем, соответствующим привязке ко всем IPv4-адресам.

  • IPv6-адрес с номером порта

    http://[0:0:0:0:0:ffff:4137:270a]:80/
    

    [::] является IPv6-аналогом IPv4-адреса 0.0.0.0.

  • Имя узла с номером порта

    http://contoso.com:80/
    http://*:80/
    

    Имена узлов, * и +, не являются особыми. Все, что не распознается как допустимый IP-адрес или localhost, привязывается ко всем IP-адресам IPv4 и IPv6. Чтобы привязать разные имена узлов к разным приложениям ASP.NET Core по одному порту, используйте HTTP.sys или обратный прокси-сервер, такой как IIS, Nginx или Apache.

    Предупреждение

    Для размещения в конфигурации обратного прокси-сервера требуется конфигурация ПО промежуточного слоя перенаправленных заголовков.

  • Имя узла localhost с номером порта или IP-адрес замыкания на себя с номером порта

    http://localhost:5000/
    http://127.0.0.1:5000/
    http://[::1]:5000/
    

    Если указать localhost, Kestrel попытается привязаться к обоим интерфейсам замыкания на себя IPv4 и IPv6. Если запрошенный порт уже используется другой службой в одном из интерфейсов замыкания на себя, Kestrel не будет запущен. Если один из интерфейсов замыкания на себя недоступен по любой другой причине (чаще всего из-за отсутствия поддержки IPv6), Kestrel зарегистрирует предупреждение.

Фильтрация узлов

Хотя Kestrel поддерживает конфигурации с использованием префиксов, например http://example.com:5000, Kestrel в основном не учитывает имя узла. Узел localhost является особым случаем, используемым для привязки к адресам замыкания на себя. Любой узел, отличный от явного IP-адреса, привязывается ко всем общедоступным IP-адресам. Заголовки Host не проверяются.

В качестве обходного решения используйте ПО промежуточного слоя фильтрации узлов. ПО промежуточного слоя фильтрации узла предоставляется пакетом Microsoft.AspNetCore.HostFiltering, который входит в метапакет Microsoft.AspNetCore.App (ASP.NET Core 2.1 или 2.2). ПО промежуточного слоя добавляется в CreateDefaultBuilder, который вызывает AddHostFiltering:

public class Program
{
    public static void Main(string[] args)
    {
        CreateWebHostBuilder(args).Build().Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>();
}

ПО промежуточного слоя фильтрации узлов отключено по умолчанию. Чтобы включить ПО промежуточного слоя, определите ключ AllowedHosts в appsettings.json /appsettings.<EnvironmentName>.json. Значение представляет собой разделенный точками с запятой список имен узлов без номеров портов:

appsettings.json:

{
  "AllowedHosts": "example.com;localhost"
}

Примечание

ПО промежуточного слоя перенаправления заголовков имеет также параметр AllowedHosts. ПО промежуточного слоя перенаправления заголовков и ПО промежуточного слоя фильтрации узлов обладают сходными возможностями для различных сценариев. Параметр AllowedHosts с ПО промежуточного слоя перенаправления заголовков подходит для случаев, когда заголовок Host не сохраняется при переадресации запросов с помощью обратного прокси-сервера или подсистемы балансировки нагрузки. Параметр AllowedHosts с ПО промежуточного слоя фильтрации узлов применим, когда Kestrel используется в качестве общедоступного пограничного сервера или если заголовок Host пересылается напрямую.

Дополнительные сведения о ПО промежуточного слоя перенаправления заголовков см. в статье Настройка ASP.NET Core для работы с прокси-серверами и подсистемами балансировки нагрузки.

Очистка запросов HTTP/1.1

Открытие HTTP-соединений занимает много времени. Для протокола HTTPS это также требует больших ресурсов. Поэтому Kestrel пытается повторно использовать подключения по протоколу HTTP/1.1. Чтобы разрешить повторное использование соединения, текст запроса должен быть полностью использован. Приложение не всегда использует текст запроса, например запросы POST, в которых сервер возвращает ответ перенаправления или 404. В случае перенаправления POST:

  • Возможно, клиент уже отправил часть данных POST.
  • Сервер записывает ответ 301.
  • Соединение нельзя использовать для нового запроса, пока не будут полностью прочитаны данные POST из предыдущего текста запроса.
  • Kestrel пытается очистить текст запроса. Очистка текста запроса означает чтение и отмену данных без их обработки.

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

  • Время ожидания очистки составляет 5 секунд. Этот параметр нельзя изменить.
  • Если все данные, указанные в заголовке Content-Length или Transfer-Encoding, не были считаны до истечения времени ожидания, соединение закрывается.

Иногда может потребоваться немедленно завершить запрос до или после записи ответа. Например, клиенты могут иметь ограничения на данные, поэтому ограничение передаваемых данных может иметь приоритет. В таких случаях для завершения запроса вызовите HttpContext.Abort из контроллера, страницы Razor или ПО промежуточного слоя.

Вызов Abort имеет определенные недостатки.

  • Создание новых подключений может выполняться очень медленно и требовать много ресурсов.
  • Нет никакой гарантии, что клиент прочитал ответ перед закрытием соединения.
  • Вызов Abort следует использовать редко и только для серьезных, а не распространенных ошибок.
    • Вызывайте Abort, только когда нужно решить конкретную проблему. Например, вызовите Abort, если вредоносные клиенты пытаются выполнить операцию POST с данными или если в клиентском коде есть ошибка, вызывающая большие или многочисленные запросы.
    • Не вызывайте Abort для распространенных ошибок, таких как HTTP 404 (не найдено).

Вызов HttpResponse.CompleteAsync перед вызовом Abort гарантирует, что сервер завершит запись ответа. Однако поведение клиента не предсказуемо. Он может не считать ответ, прежде чем подключение будет прервано.

Этот процесс отличается для HTTP/2, так как протокол поддерживает прерывание отдельных потоков запросов без закрытия соединения. 5-секундное время ожидания очистки не применяется. Если после завершения ответа сервер содержит непрочтенные данные текста запроса, он отправляет кадр HTTP/2 RST. Дополнительные кадры данных текста запроса игнорируются.

По возможности клиентам лучше использовать заголовок запроса Expect: 100-continue и дожидаться ответа сервера перед началом отправки текста запроса. Это дает клиенту возможность проверить ответ и прервать операцию перед отправкой ненужных данных.

Дополнительные ресурсы

Kestrel — это кроссплатформенный веб-сервер для ASP.NET Core. Kestrel — это веб-сервер, который по умолчанию включается в шаблоны проектов ASP.NET Core.

Kestrel поддерживается в следующих сценариях:

  • HTTPS
  • Непрозрачное обновление для поддержки WebSocket
  • Сокеты UNIX для повышения производительности при работе за Nginx

Kestrel поддерживается на всех платформах и во всех версиях, поддерживаемых .NET Core.

Просмотреть или скачать образец кода (как скачивать)

Использование Kestrel с обратным прокси-сервером

Kestrel можно использовать отдельно или с обратным прокси-сервером, таким как IIS, Nginx или Apache. Обратный прокси-сервер получает HTTP-запросы из сети и пересылает их в Kestrel.

Kestrel используется в качестве пограничного (с выходом в Интернет) веб-сервера:

Kestrel взаимодействует с Интернетом напрямую без обратного прокси-сервера

Kestrel используется в конфигурации обратного прокси-сервера.

Kestrel косвенно обменивается данными с Интернетом через обратный прокси-сервер, такой как IIS, Nginx или Apache

Любая из этих конфигураций — с обратным прокси-сервером и без него — является поддерживаемой конфигурацией для размещения.

Kestrel, используемый в качестве пограничного сервера без обратного прокси-сервера, не поддерживает обращение нескольких процессов к одним и тем же IP-адресам и портам. Когда Kestrel настроен на прослушивание порта, Kestrel обрабатывает весь трафик для этого порта независимо от заголовков запросов Host. Обратный прокси-сервер, который может совместно использовать порты, также может пересылать запросы в Kestrel с уникальными IP-адресом и портом.

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

Обратный прокси-сервер:

  • Может ограничить общедоступную контактную зону размещенных на нем приложений.
  • Предоставляет дополнительный уровень конфигурации и защиты.
  • Может лучше интегрироваться с существующей инфраструктурой.
  • Упрощает настройку балансировки нагрузки и безопасных подключений (HTTPS). Сертификат X.509 требуется только обратному прокси-серверу, а сам этот сервер может обмениваться данными с серверами приложения во внутренней сети по обычному протоколу HTTP.

Предупреждение

Для размещения в конфигурации обратного прокси-сервера требуется конфигурация ПО промежуточного слоя перенаправленных заголовков.

Использование Kestrel в приложениях ASP.NET Core

Пакет Microsoft.AspNetCore.Server.Kestrel входит в состав метапакета Microsoft.AspNetCore.App.

Шаблоны проектов ASP.NET Core используют Kestrel по умолчанию. В файле Program.cs код шаблона вызывает метод CreateDefaultBuilder, который в фоновом режиме вызывает UseKestrel.

Чтобы задать дополнительную конфигурацию после вызова CreateDefaultBuilder, вызовите UseKestrel:

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .UseKestrel(serverOptions =>
        {
            // Set properties and call methods on serverOptions
        });

Дополнительные сведения о CreateDefaultBuilder и построении узла, см. в разделе Настройка узла, разделы Веб-узел ASP.NET Core.

Параметры Kestrel

Веб-сервер Kestrel имеет ограничивающие параметры конфигурации, которые удобно использовать в развертываниях с выходом в Интернет.

Задать ограничения для свойства Limits в классе KestrelServerOptions. Свойство Limits содержит экземпляр класса KestrelServerLimits.

В следующих примерах используется пространство имен Microsoft.AspNetCore.Server.Kestrel.Core.

using Microsoft.AspNetCore.Server.Kestrel.Core;

Параметры Kestrel, которые настраиваются в коде C# в следующих примерах, можно также задать с помощью поставщика конфигурации. Например, поставщик конфигурации файла может загрузить конфигурацию Kestrel из файла appsettings.json или appsettings.{Environment}.json:

{
  "Kestrel": {
    "Limits": {
      "MaxConcurrentConnections": 100,
      "MaxConcurrentUpgradedConnections": 100
    }
  }
}

Воспользуйтесь одним из перечисленных ниже подходов.

  • Настройте Kestrel в Startup.ConfigureServices:

    1. Внедрение экземпляра IConfiguration в класс Startup. В следующем примере предполагается, что введенная конфигурация назначается свойству Configuration.

    2. В Startup.ConfigureServices загрузите раздел конфигурации Kestrel в конфигурацию Kestrel:

      using Microsoft.Extensions.Configuration
      
      public class Startup
      {
          public Startup(IConfiguration configuration)
          {
              Configuration = configuration;
          }
      
          public IConfiguration Configuration { get; }
      
          public void ConfigureServices(IServiceCollection services)
          {
              services.Configure<KestrelServerOptions>(
                  Configuration.GetSection("Kestrel"));
          }
      
          public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
          {
              ...
          }
      }
      
  • Настройте Kestrel при создании узла:

    В Program.cs загрузите раздел конфигурации Kestrel в конфигурацию Kestrel.

    // using Microsoft.Extensions.DependencyInjection;
    
    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .ConfigureServices((context, services) =>
            {
                services.Configure<KestrelServerOptions>(
                    context.Configuration.GetSection("Kestrel"));
            })
            .UseStartup<Startup>();
    

Оба предыдущих подхода работают с любым поставщиком конфигурации.

Время ожидания проверки на активность

KeepAliveTimeout

Получает или задает время ожидания проверки на активность. Значение по умолчанию — 2 минуты.

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .UseKestrel(serverOptions =>
        {
            serverOptions.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(2);
        });

максимальное число клиентских подключений;

MaxConcurrentConnections MaxConcurrentUpgradedConnections

Максимальное число одновременно открытых подключений TCP для всего приложения можно задать с помощью следующего кода:

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .UseKestrel(serverOptions =>
        {
            serverOptions.Limits.MaxConcurrentConnections = 100;
        });

Существует отдельный предел по подключениям, измененным с HTTP или HTTPS на другой протокол (например, по запросу WebSocket). После изменения подключение не учитывается в пределе MaxConcurrentConnections.

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .UseKestrel(serverOptions =>
        {
            serverOptions.Limits.MaxConcurrentUpgradedConnections = 100;
        });

По умолчанию максимальное число подключений не ограничено (null).

максимальный размер текста запроса;

MaxRequestBodySize

По умолчанию максимальный размер текста запроса составляет 30 000 000 байт, что примерно соответствует 28,6 МБ.

Чтобы переопределить это ограничение в приложении MVC ASP.NET Core, мы рекомендуем использовать атрибут RequestSizeLimitAttribute в методе действия:

[RequestSizeLimit(100000000)]
public IActionResult MyActionMethod()

Приведенный ниже пример показывает, как настроить ограничение для приложения и каждого запроса:

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .UseKestrel(serverOptions =>
        {
            serverOptions.Limits.MaxRequestBodySize = 10 * 1024;
        });

Переопределите параметр для конкретного запроса в ПО промежуточного слоя:

app.Run(async (context) =>
{
    context.Features.Get<IHttpMaxRequestBodySizeFeature>()
        .MaxRequestBodySize = 10 * 1024;

    var minRequestRateFeature = 
        context.Features.Get<IHttpMinRequestBodyDataRateFeature>();
    var minResponseRateFeature = 
        context.Features.Get<IHttpMinResponseDataRateFeature>();

    if (minRequestRateFeature != null)
    {
        minRequestRateFeature.MinDataRate = new MinDataRate(
            bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    }

    if (minResponseRateFeature != null)
    {
        minResponseRateFeature.MinDataRate = new MinDataRate(
            bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
    }

Если приложение пытается настроить ограничение для запроса после того, как оно начало считывать запрос, возникает исключение. Доступно свойство IsReadOnly, указывающее, что свойство MaxRequestBodySize находится в состоянии только для чтения и настраивать ограничение слишком поздно.

При запуске приложения вне процесса, который обслуживает модуль ASP.NET Core, ограничение на размер текста запроса Kestrel будет отключено, так как оно уже задается IIS.

минимальная скорость передачи данных в тексте запроса.

MinRequestBodyDataRate MinResponseDataRate

Kestrel каждую секунду проверяет, поступают ли данные с указанной скоростью в байтах в секунду. Если скорость падает ниже минимума, для подключения истекает время ожидания. Льготный период — это время, которое Kestrel предоставляет клиенту для увеличения скорости отправки до минимального уровня; в течение этого периода скорость не проверяется. Льготный период помогает избежать разрыва соединений, которые первоначально отправляют данные с небольшой скоростью из-за медленного запуска TCP.

Минимальная скорость по умолчанию составляет 240 байт/с, льготный период равен 5 секундам.

Минимальная скорость также применяется к отклику. Код для задания лимита запросов и лимита откликов различается только наличием RequestBody или Response в именах свойств и интерфейсов.

Ниже приведен пример, показывающий, как настроить минимальную скорость передачи данных в Program.cs:

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .UseKestrel(serverOptions =>
        {
            serverOptions.Limits.MinRequestBodyDataRate =
                new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
            serverOptions.Limits.MinResponseDataRate =
                new MinDataRate(bytesPerSecond: 100, gracePeriod: TimeSpan.FromSeconds(10));
        });

Время ожидания для заголовков запросов

RequestHeadersTimeout

Получает или задает максимальное время, которое сервер уделяет получению заголовков запросов. Значение по умолчанию — 30 секунд.

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .UseKestrel(serverOptions =>
        {
            serverOptions.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(1);
        });

Синхронный ввод-вывод

AllowSynchronousIO определяет, разрешены ли синхронные операции ввода-вывода для запроса и ответа. Значение по умолчанию — true.

Предупреждение

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

В примере ниже отключаются синхронные операции ввода-вывода:

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .UseKestrel(serverOptions =>
        {
            serverOptions.AllowSynchronousIO = false;
        });

Сведения о других параметрах и ограничениях Kestrel см. в следующих разделах:

Конфигурация конечной точки

По умолчанию платформа ASP.NET Core привязана к:

  • http://localhost:5000
  • https://localhost:5001 (если присутствует локальный сертификат разработки)

Укажите URL-адреса с помощью следующих параметров:

  • Переменная среды ASPNETCORE_URLS.
  • Аргументы командной строки --urls.
  • Ключ конфигурации узла urls.
  • Метод расширения UseUrls.

Значение, указанное с помощью этих подходов, может быть одной или несколькими конечными точками HTTP и HTTPS (HTTPS при наличии сертификата по умолчанию). Настройте значение в виде списка с разделением точкой с запятой (например, "Urls": "http://localhost:8000;http://localhost:8001").

Дополнительные сведения о таких подходах см. в разделах URL-адреса сервера и Переопределение конфигурации.

Сертификат разработки создается, когда:

В некоторых браузерах требуется явное разрешение доверять локальному сертификату разработки.

Шаблоны проектов настраивают приложения так, чтобы они запускались на базе HTTPS по умолчанию и включали поддержку перенаправления HTTPS и HSTS.

Вызовите методы Listen или ListenUnixSocket из KestrelServerOptions, чтобы настроить префиксы URL-адресов и порты для Kestrel.

UseUrls, аргумент командной строки --urls, ключ конфигурации узла urls и переменная среды ASPNETCORE_URLS тоже работают, однако на них распространяются ограничения, указанные далее в этой статье (для конфигурации конечной точки HTTPS требуется сертификат по умолчанию).

Конфигурация KestrelServerOptions:

ConfigureEndpointDefaults(Action<ListenOptions>)

Указывает конфигурацию Action для выполнения каждой заданной конечной точки. Если вызвать ConfigureEndpointDefaults несколько раз, предыдущие элементы Action будут заменены последним элементом Action.

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .ConfigureKestrel((context, serverOptions) =>
        {
            serverOptions.ConfigureEndpointDefaults(listenOptions =>
            {
                // Configure endpoint defaults
            });
        });

Примечание

К конечным точкам, созданным путем вызова Listen перед вызовом ConfigureEndpointDefaults, не будут применяться значения по умолчанию.

ConfigureHttpsDefaults(Action<HttpsConnectionAdapterOptions>)

Указывает конфигурацию Action для выполнения каждой конечной точки HTTPS. Если вызвать ConfigureHttpsDefaults несколько раз, предыдущие элементы Action будут заменены последним элементом Action.

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .ConfigureKestrel((context, serverOptions) =>
        {
            serverOptions.ConfigureHttpsDefaults(listenOptions =>
            {
                // certificate is an X509Certificate2
                listenOptions.ServerCertificate = certificate;
            });
        });

Примечание

К конечным точкам, созданным путем вызова Listen перед вызовом ConfigureHttpsDefaults, не будут применяться значения по умолчанию.

Configure(IConfiguration)

Создает загрузчик конфигурации для настройки Kestrel, который принимает IConfiguration в качестве входных данных. Для Kestrel конфигурация должна быть ограничена разделом конфигурации.

ListenOptions.UseHttps

Настройте Kestrel для использования протокола HTTPS.

Расширения ListenOptions.UseHttps:

  • UseHttps: настройте Kestrel для использования протокола HTTPS с сертификатом по умолчанию. Создает исключение, если сертификат по умолчанию не настроен.
  • UseHttps(string fileName)
  • UseHttps(string fileName, string password)
  • UseHttps(string fileName, string password, Action<HttpsConnectionAdapterOptions> configureOptions)
  • UseHttps(StoreName storeName, string subject)
  • UseHttps(StoreName storeName, string subject, bool allowInvalid)
  • UseHttps(StoreName storeName, string subject, bool allowInvalid, StoreLocation location)
  • UseHttps(StoreName storeName, string subject, bool allowInvalid, StoreLocation location, Action<HttpsConnectionAdapterOptions> configureOptions)
  • UseHttps(X509Certificate2 serverCertificate)
  • UseHttps(X509Certificate2 serverCertificate, Action<HttpsConnectionAdapterOptions> configureOptions)
  • UseHttps(Action<HttpsConnectionAdapterOptions> configureOptions)

Параметры ListenOptions.UseHttps:

  • filename — это путь и имя файла сертификата, связанного с каталогом, где находятся файлы содержимого приложения.
  • password — это пароль для доступа к данным сертификата X.509.
  • configureOptions — это Action для настройки HttpsConnectionAdapterOptions. Возвращает ListenOptions.
  • storeName — это хранилище сертификатов, из которого выполняется загрузка сертификата.
  • subject — это имя субъекта для сертификата.
  • allowInvalid указывает, следует ли учитывать недопустимые сертификаты, например самозаверяющие сертификаты.
  • location — это расположение хранилища, из которого загружается сертификат.
  • serverCertificate — это сертификат X.509.

В рабочей среде необходимо явно настроить HTTPS. Как минимум необходимо указать сертификат по умолчанию.

Поддерживаемые конфигурации, описанные далее:

  • Отсутствие конфигурации
  • Замена сертификата по умолчанию из конфигурации
  • Изменение значений по умолчанию в коде

Отсутствие конфигурации

Kestrel ожидает передачи данных через http://localhost:5000 и https://localhost:5001 (если доступен сертификат по умолчанию).

Замена сертификата по умолчанию из конфигурации

CreateDefaultBuilder по умолчанию вызывает Configure(context.Configuration.GetSection("Kestrel")), чтобы загрузить конфигурацию Kestrel. Kestrel имеет доступ к схеме конфигурации параметров приложения HTTPS по умолчанию. Настройте несколько конечных точек, включая URL-адреса и сертификаты для использования, либо из файла на диске, либо из хранилища сертификатов.

В следующем примере appsettings.json :

  • Установите для AllowInvalid значение true, чтобы разрешить использование недопустимых сертификатов (например, самозаверяющих сертификатов).
  • Любая конечная точка HTTPS, которая не указывает сертификат (HttpsDefaultCert в следующем примере), будет использовать сертификат, определенный в разделе Certificates (Сертификаты) > Default (По умолчанию), или сертификат разработки.
{
  "Kestrel": {
    "Endpoints": {
      "Http": {
        "Url": "http://localhost:5000"
      },

      "HttpsInlineCertFile": {
        "Url": "https://localhost:5001",
        "Certificate": {
          "Path": "<path to .pfx file>",
          "Password": "<certificate password>"
        }
      },

      "HttpsInlineCertStore": {
        "Url": "https://localhost:5002",
        "Certificate": {
          "Subject": "<subject; required>",
          "Store": "<certificate store; required>",
          "Location": "<location; defaults to CurrentUser>",
          "AllowInvalid": "<true or false; defaults to false>"
        }
      },

      "HttpsDefaultCert": {
        "Url": "https://localhost:5003"
      },

      "Https": {
        "Url": "https://*:5004",
        "Certificate": {
          "Path": "<path to .pfx file>",
          "Password": "<certificate password>"
        }
      }
    },
    "Certificates": {
      "Default": {
        "Path": "<path to .pfx file>",
        "Password": "<certificate password>"
      }
    }
  }
}

Вместо использования параметров Path и Password для узла сертификата можно указать сертификат с помощью полей хранилища сертификатов. Например, сертификат из раздела Сертификаты > По умолчанию можно указать следующим образом:

"Default": {
  "Subject": "<subject; required>",
  "Store": "<cert store; required>",
  "Location": "<location; defaults to CurrentUser>",
  "AllowInvalid": "<true or false; defaults to false>"
}

Примечания к схеме.

  • Регистр букв в именах конечных точек не учитывается. Например, HTTPS и Https являются допустимыми.
  • Параметр Url является обязательным для каждой конечной точки. Формат этого параметра такой же, как для параметра конфигурации Urls верхнего уровня, только он ограничен одиночным значением.
  • Эти конечные точки заменяют конечные точки, определенные в конфигурации Urls верхнего уровня, а не дополняют их. Конечные точки, определенные в коде через Listen, объединяются с конечными точками, определенными в разделе конфигурации.
  • Раздел Certificate является необязательным. Если раздел Certificate не указан, используются значения по умолчанию, определенные в предыдущих сценариях. Если значений по умолчанию нет, сервер выдает исключение и не запускается.
  • Раздел Certificate поддерживает сертификаты PathPassword и SubjectStore.
  • Таким образом, можно определить любое количество конечных точек, если это не приводит к конфликту портов.
  • options.Configure(context.Configuration.GetSection("{SECTION}")) возвращает KestrelConfigurationLoader с методом .Endpoint(string name, listenOptions => { }), который может использоваться в качестве дополнения для параметров настроенной конечной точки:
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .UseKestrel((context, serverOptions) =>
        {
            serverOptions.Configure(context.Configuration.GetSection("Kestrel"))
                .Endpoint("HTTPS", listenOptions =>
                {
                    listenOptions.HttpsOptions.SslProtocols = SslProtocols.Tls12;
                });
        });

Можно обратиться напрямую к KestrelServerOptions.ConfigurationLoader, чтобы и далее выполнять итерацию с существующим загрузчиком, например, предоставленным CreateDefaultBuilder.

  • Раздел конфигурации для каждой конечной точки доступен в параметрах в методе Endpoint, чтобы можно было прочитать пользовательские параметры.
  • Можно загрузить несколько конфигураций, снова вызвав options.Configure(context.Configuration.GetSection("{SECTION}")) с другим разделом. Используется только последняя конфигурация, если явным образом не вызвать Load в предыдущих экземплярах. Метапакет не вызывает Load, чтобы можно было заменить его раздел конфигурации по умолчанию.
  • KestrelConfigurationLoader отражает семейство API Listen из KestrelServerOptions как перегрузки Endpoint, чтобы можно было настроить конечные точки кода и конфигурации в одном месте. Эти перегрузки не используют имена и используют только параметры по умолчанию из конфигурации.

Изменение значений по умолчанию в коде

Можно использовать ConfigureEndpointDefaults и ConfigureHttpsDefaults для изменения параметров по умолчанию для ListenOptions и HttpsConnectionAdapterOptions, включая переопределение сертификата по умолчанию, указанного в предыдущем сценарии. Необходимо вызвать ConfigureEndpointDefaults и ConfigureHttpsDefaults, прежде чем настраивать конечные точки.

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .UseKestrel((context, serverOptions) =>
        {
            serverOptions.ConfigureEndpointDefaults(listenOptions =>
            {
                // Configure endpoint defaults
            });

            serverOptions.ConfigureHttpsDefaults(listenOptions =>
            {
                listenOptions.SslProtocols = SslProtocols.Tls12;
            });
        });

Поддержка SNI в Kestrel

Можно использовать указание имени сервера (SNI) для размещения нескольких доменов в одном IP-адресе и порте. Для использования SNI клиент отправляет имя узла для безопасного сеанса серверу во время подтверждения TLS, чтобы сервер предоставил правильный сертификат. Клиент использует предоставленный сертификат для зашифрованного соединения с сервером во время безопасного сеанса, который следует после подтверждения TLS.

Kestrel поддерживает SNI через обратный вызов ServerCertificateSelector. Функция обратного вызова используется один раз за подключение, чтобы приложение проверило имя узла и выбрало соответствующий сертификат.

Поддержка SNI требует:

  • Запуск на целевой платформе netcoreapp2.1 или более поздней версии. В net461 или более поздней версии обратный вызов выполняется, но name всегда имеет значение null. name также имеет значение null, если клиент не предоставляет параметр имени узла при подтверждении TLS.
  • Все веб-сайты выполняются на одном и том же экземпляре Kestrel. Kestrel не поддерживает совместное использование IP-адреса и порта на нескольких экземплярах без обратного прокси-сервера.
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .UseKestrel((context, serverOptions) =>
        {
            serverOptions.ListenAnyIP(5005, listenOptions =>
            {
                listenOptions.UseHttps(httpsOptions =>
                {
                    var localhostCert = CertificateLoader.LoadFromStoreCert(
                        "localhost", "My", StoreLocation.CurrentUser,
                        allowInvalid: true);
                    var exampleCert = CertificateLoader.LoadFromStoreCert(
                        "example.com", "My", StoreLocation.CurrentUser,
                        allowInvalid: true);
                    var subExampleCert = CertificateLoader.LoadFromStoreCert(
                        "sub.example.com", "My", StoreLocation.CurrentUser,
                        allowInvalid: true);
                    var certs = new Dictionary<string, X509Certificate2>(
                        StringComparer.OrdinalIgnoreCase);
                    certs["localhost"] = localhostCert;
                    certs["example.com"] = exampleCert;
                    certs["sub.example.com"] = subExampleCert;

                    httpsOptions.ServerCertificateSelector = (connectionContext, name) =>
                    {
                        if (name != null && certs.TryGetValue(name, out var cert))
                        {
                            return cert;
                        }

                        return exampleCert;
                    };
                });
            });
        })
        .Build();

Ведение журнала подключения

Вызовите UseConnectionLogging, чтобы выдать журналы уровня отладки для обмена данными на уровне байтов в рамках подключения. Ведение журнала подключения полезно для устранения неполадок, связанных с низкоуровневым взаимодействием, например при TLS-шифровании и работе за прокси-серверами. Если UseConnectionLogging поместить перед UseHttps, в журнале регистрируется зашифрованный трафик. Если UseConnectionLogging поместить после UseHttps, в журнале регистрируется расшифрованный трафик.

webBuilder.ConfigureKestrel(serverOptions =>
{
    serverOptions.Listen(IPAddress.Any, 8000, listenOptions =>
    {
        listenOptions.UseConnectionLogging();
    });
});

Привязка к TCP-сокету

Метод Listen выполняет привязку к TCP-сокету, а лямбда-выражение параметров позволяет настроить конфигурацию сертификата X.509:

public static void Main(string[] args)
{
    CreateWebHostBuilder(args).Build().Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .UseKestrel(serverOptions =>
        {
            serverOptions.Listen(IPAddress.Loopback, 5000);
            serverOptions.Listen(IPAddress.Loopback, 5001, listenOptions =>
            {
                listenOptions.UseHttps("testCert.pfx", "testPassword");
            });
        });
public static void Main(string[] args)
{
    CreateWebHostBuilder(args).Build().Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .UseKestrel(serverOptions =>
        {
            serverOptions.Listen(IPAddress.Loopback, 5000);
            serverOptions.Listen(IPAddress.Loopback, 5001, listenOptions =>
            {
                listenOptions.UseHttps("testCert.pfx", "testPassword");
            });
        });

В этом примере настраивается HTTPS для конечной точки с помощью ListenOptions. С помощью этого API можно настроить и другие параметры Kestrel для отдельных конечных точек.

В Windows самозаверяющие сертификаты создаются с помощью командлета PowerShell New-SelfSignedCertificate. Примеры, которые не поддерживаются, см. в разделе UpdateIISExpressSSLForChrome.ps1.

В macOS, Linux и Windows сертификаты создаются с помощью OpenSSL.

Привязка к сокету UNIX

Вы можете прослушивать сокет UNIX с помощью ListenUnixSocket, чтобы улучшить производительность Nginx, как показано в следующем примере:

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .UseKestrel(serverOptions =>
        {
            serverOptions.ListenUnixSocket("/tmp/kestrel-test.sock");
            serverOptions.ListenUnixSocket("/tmp/kestrel-test.sock", listenOptions =>
            {
                listenOptions.UseHttps("testCert.pfx", "testpassword");
            });
        });
  • В файле конфигурации Nginx установите для записи server > location > proxy_pass значение http://unix:/tmp/{KESTREL SOCKET}:/;. {KESTREL SOCKET} — это имя сокета, предоставленного для ListenUnixSocket (как kestrel-test.sock в предыдущем примере).
  • Убедитесь, что сокет доступен для записи Nginx (например, chmod go+w /tmp/kestrel-test.sock).

Порт 0

Если указать номер порта 0, Kestrel будет динамически привязан к доступному порту. В следующем примере показано, как определить, к какому порту фактически привязан Kestrel во время выполнения:

public void Configure(IApplicationBuilder app)
{
    var serverAddressesFeature = 
        app.ServerFeatures.Get<IServerAddressesFeature>();

    app.UseStaticFiles();

    app.Run(async (context) =>
    {
        context.Response.ContentType = "text/html";
        await context.Response
            .WriteAsync("<!DOCTYPE html><html lang=\"en\"><head>" +
                "<title></title></head><body><p>Hosted by Kestrel</p>");

        if (serverAddressesFeature != null)
        {
            await context.Response
                .WriteAsync("<p>Listening on the following addresses: " +
                    string.Join(", ", serverAddressesFeature.Addresses) +
                    "</p>");
        }

        await context.Response.WriteAsync("<p>Request URL: " +
            $"{context.Request.GetDisplayUrl()}<p>");
    });
}

Когда приложение выполняется, в выходных данных в окне консоли указывается динамический порт, по которому можно связаться с приложением:

Listening on the following addresses: http://127.0.0.1:48508

Ограничения

Настройте конечные точки с помощью следующих подходов:

  • UseUrls
  • Аргументы командной строки --urls.
  • Ключ конфигурации узла urls.
  • Переменная среды ASPNETCORE_URLS.

Эти методы удобны, если нужно, чтобы код работал с серверами, отличающимися от Kestrel. Не забывайте о следующих ограничениях.

  • С этими подходами нельзя использовать HTTPS, если в конфигурации конечной точки HTTPS не предоставлен сертификат по умолчанию (например, с помощью конфигурации KestrelServerOptions или файла конфигурации, как показано выше в этом разделе).
  • Если подходы Listen и UseUrls используются одновременно, конечные точки Listen переопределяют конечные точки UseUrls.

Конфигурация конечной точки IIS

При использовании служб IIS привязки URL-адресов для IIS переопределяют привязки, заданные Listen или UseUrls. Дополнительные сведения см. в статье Модуль ASP.NET Core.

Конфигурация транспорта Libuv

После выпуска ASP.NET Core 2.1 транспорт Kestrel по умолчанию основан не на Libuv, а на управляемых сокетах. Это критическое изменение для приложений ASP.NET Core 2.0, которые обновляются до версии 2.1, если они вызывают UseLibuv и зависят от одного из следующих пакетов:

Для проектов, где требуется использовать Libuv:

  • Добавьте зависимость для пакета Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv в файл проекта приложения:

    <PackageReference Include="Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv"
                      Version="{VERSION}" />
    
  • Вызов UseLibuv:

    public class Program
    {
        public static void Main(string[] args)
        {
            CreateWebHostBuilder(args).Build().Run();
        }
    
        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseLibuv()
                .UseStartup<Startup>();
    }
    

Префиксы URL-адресов

Если вы используете UseUrls, аргумент командной строки --urls, ключ конфигурации узла urls или переменную среды ASPNETCORE_URLS, префиксы URL-адресов могут иметь любой из указанных ниже форматов.

Допустимы только префиксы URL-адресов HTTP. Kestrel не поддерживает HTTP при настройке привязок URL-адресов с помощью UseUrls.

  • IPv4-адрес с номером порта

    http://65.55.39.10:80/
    

    0.0.0.0 является особым случаем, соответствующим привязке ко всем IPv4-адресам.

  • IPv6-адрес с номером порта

    http://[0:0:0:0:0:ffff:4137:270a]:80/
    

    [::] является IPv6-аналогом IPv4-адреса 0.0.0.0.

  • Имя узла с номером порта

    http://contoso.com:80/
    http://*:80/
    

    Имена узлов, * и +, не являются особыми. Все, что не распознается как допустимый IP-адрес или localhost, привязывается ко всем IP-адресам IPv4 и IPv6. Чтобы привязать разные имена узлов к разным приложениям ASP.NET Core по одному порту, используйте HTTP.sys или обратный прокси-сервер, такой как IIS, Nginx или Apache.

    Предупреждение

    Для размещения в конфигурации обратного прокси-сервера требуется конфигурация ПО промежуточного слоя перенаправленных заголовков.

  • Имя узла localhost с номером порта или IP-адрес замыкания на себя с номером порта

    http://localhost:5000/
    http://127.0.0.1:5000/
    http://[::1]:5000/
    

    Если указать localhost, Kestrel попытается привязаться к обоим интерфейсам замыкания на себя IPv4 и IPv6. Если запрошенный порт уже используется другой службой в одном из интерфейсов замыкания на себя, Kestrel не будет запущен. Если один из интерфейсов замыкания на себя недоступен по любой другой причине (чаще всего из-за отсутствия поддержки IPv6), Kestrel зарегистрирует предупреждение.

Фильтрация узлов

Хотя Kestrel поддерживает конфигурации с использованием префиксов, например http://example.com:5000, Kestrel в основном не учитывает имя узла. Узел localhost является особым случаем, используемым для привязки к адресам замыкания на себя. Любой узел, отличный от явного IP-адреса, привязывается ко всем общедоступным IP-адресам. Заголовки Host не проверяются.

В качестве обходного решения используйте ПО промежуточного слоя фильтрации узлов. ПО промежуточного слоя фильтрации узла предоставляется пакетом Microsoft.AspNetCore.HostFiltering, который входит в метапакет Microsoft.AspNetCore.App (ASP.NET Core 2.1 или 2.2). ПО промежуточного слоя добавляется в CreateDefaultBuilder, который вызывает AddHostFiltering:

public class Program
{
    public static void Main(string[] args)
    {
        CreateWebHostBuilder(args).Build().Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>();
}

ПО промежуточного слоя фильтрации узлов отключено по умолчанию. Чтобы включить ПО промежуточного слоя, определите ключ AllowedHosts в appsettings.json /appsettings.<EnvironmentName>.json. Значение представляет собой разделенный точками с запятой список имен узлов без номеров портов:

appsettings.json:

{
  "AllowedHosts": "example.com;localhost"
}

Примечание

ПО промежуточного слоя перенаправления заголовков имеет также параметр AllowedHosts. ПО промежуточного слоя перенаправления заголовков и ПО промежуточного слоя фильтрации узлов обладают сходными возможностями для различных сценариев. Параметр AllowedHosts с ПО промежуточного слоя перенаправления заголовков подходит для случаев, когда заголовок Host не сохраняется при переадресации запросов с помощью обратного прокси-сервера или подсистемы балансировки нагрузки. Параметр AllowedHosts с ПО промежуточного слоя фильтрации узлов применим, когда Kestrel используется в качестве общедоступного пограничного сервера или если заголовок Host пересылается напрямую.

Дополнительные сведения о ПО промежуточного слоя перенаправления заголовков см. в статье Настройка ASP.NET Core для работы с прокси-серверами и подсистемами балансировки нагрузки.

Очистка запросов HTTP/1.1

Открытие HTTP-соединений занимает много времени. Для протокола HTTPS это также требует больших ресурсов. Поэтому Kestrel пытается повторно использовать подключения по протоколу HTTP/1.1. Чтобы разрешить повторное использование соединения, текст запроса должен быть полностью использован. Приложение не всегда использует текст запроса, например запросы POST, в которых сервер возвращает ответ перенаправления или 404. В случае перенаправления POST:

  • Возможно, клиент уже отправил часть данных POST.
  • Сервер записывает ответ 301.
  • Соединение нельзя использовать для нового запроса, пока не будут полностью прочитаны данные POST из предыдущего текста запроса.
  • Kestrel пытается очистить текст запроса. Очистка текста запроса означает чтение и отмену данных без их обработки.

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

  • Время ожидания очистки составляет 5 секунд. Этот параметр нельзя изменить.
  • Если все данные, указанные в заголовке Content-Length или Transfer-Encoding, не были считаны до истечения времени ожидания, соединение закрывается.

Иногда может потребоваться немедленно завершить запрос до или после записи ответа. Например, клиенты могут иметь ограничения на данные, поэтому ограничение передаваемых данных может иметь приоритет. В таких случаях для завершения запроса вызовите HttpContext.Abort из контроллера, страницы Razor или ПО промежуточного слоя.

Вызов Abort имеет определенные недостатки.

  • Создание новых подключений может выполняться очень медленно и требовать много ресурсов.
  • Нет никакой гарантии, что клиент прочитал ответ перед закрытием соединения.
  • Вызов Abort следует использовать редко и только для серьезных, а не распространенных ошибок.
    • Вызывайте Abort, только когда нужно решить конкретную проблему. Например, вызовите Abort, если вредоносные клиенты пытаются выполнить операцию POST с данными или если в клиентском коде есть ошибка, вызывающая большие или многочисленные запросы.
    • Не вызывайте Abort для распространенных ошибок, таких как HTTP 404 (не найдено).

Вызов HttpResponse.CompleteAsync перед вызовом Abort гарантирует, что сервер завершит запись ответа. Однако поведение клиента не предсказуемо. Он может не считать ответ, прежде чем подключение будет прервано.

Этот процесс отличается для HTTP/2, так как протокол поддерживает прерывание отдельных потоков запросов без закрытия соединения. 5-секундное время ожидания очистки не применяется. Если после завершения ответа сервер содержит непрочтенные данные текста запроса, он отправляет кадр HTTP/2 RST. Дополнительные кадры данных текста запроса игнорируются.

По возможности клиентам лучше использовать заголовок запроса Expect: 100-continue и дожидаться ответа сервера перед началом отправки текста запроса. Это дает клиенту возможность проверить ответ и прервать операцию перед отправкой ненужных данных.

Дополнительные ресурсы