Http1AndHttp2AndHttp3 никогда не выбирает http2 вместо httpC#

Место общения программистов C#
Ответить
Anonymous
 Http1AndHttp2AndHttp3 никогда не выбирает http2 вместо http

Сообщение Anonymous »

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

Код: Выделить всё

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Hosting;
using Microsoft.AspNetCore.Server.Kestrel.Core;

var builder = WebApplication.CreateBuilder(args);

// Configure Kestrel for h2c (HTTP/2 without TLS)
builder.WebHost.ConfigureKestrel(options =>
{
// Listen on port 5000 for h2c (HTTP/2 without TLS)
options.ListenAnyIP(5000, listenOptions =>
{
listenOptions.Protocols = HttpProtocols.Http2; // Only HTTP/2 Cleartext (h2c)
});

// Optionally, listen on port 5001 for HTTP/1 and HTTP/2 with TLS
options.ListenAnyIP(5001, listenOptions =>
{
listenOptions.Protocols = HttpProtocols.Http1AndHttp2;
listenOptions.UseHttps(); // HTTP/1.x and HTTP/2 with TLS
});

// Optionally, listen on port 5002 for HTTP/1 and HTTP/2 and HTTP/3 with TLS
options.ListenAnyIP(5002, listenOptions =>
{
listenOptions.Protocols = HttpProtocols.Http1AndHttp2AndHttp3;
listenOptions.UseHttps(); // HTTP/1.x and HTTP/2 with TLS
});

options.ListenAnyIP(5003, listenOptions =>
{
listenOptions.Protocols = HttpProtocols.Http1AndHttp2;
});

options.ListenAnyIP(5004, listenOptions =>
{
listenOptions.Protocols = HttpProtocols.Http1AndHttp2AndHttp3;
});

options.ListenAnyIP(5005, listenOptions =>
{
listenOptions.Protocols = HttpProtocols.Http3;
listenOptions.UseHttps(); // HTTP/1.x and HTTP/2 with TLS
});

options.ListenAnyIP(5006, listenOptions =>
{
listenOptions.Protocols = HttpProtocols.Http1AndHttp2AndHttp3;
listenOptions.UseHttps(); // HTTP/1.x and HTTP/2 with TLS
});

options.ListenAnyIP(5007, listenOptions =>
{
listenOptions.Protocols = HttpProtocols.Http1;
listenOptions.UseHttps(); // HTTP/1.x and HTTP/2 with TLS
});
});

var app = builder.Build();

app.MapGet("/", (HttpContext context) =>
{
// Check if the request is using HTTP/2 (h2c)
if (context.Request.Protocol == "HTTP/2")
{
return Results.Text("Hello from HTTP/2");
}

// Check if the request is using HTTP/2 (h2c)
if (context.Request.Protocol == "HTTP/3")
{
return Results.Text("Hello from HTTP/3");
}

return Results.Text("Hello from HTTP/1.x or HTTPS");
});

app.Run();
Приведенный ниже прослушиватель, который я ожидал принять соединение через http2, если я укажу от клиента отправить соединение только с http2 или выше (политика — RequestVersionOrHigher), но неожиданно я получаю следующее error Произошла ошибка: сервер HTTP/2 закрыл соединение. Код ошибки HTTP/2 «HTTP_1_1_REQUIRED» (0xd). (HttpProtocolError)

Код: Выделить всё

    options.ListenAnyIP(5004, listenOptions =>
{
listenOptions.Protocols = HttpProtocols.Http1AndHttp2AndHttp3;
});

Код: Выделить всё

Enter the server port (default is 5004): 5004
Enter Schema: (http, https): http
Select the HTTP version:
1 - HTTP/1.1
2 - HTTP/2
3 - HTTP/3 (if supported)
2
Select the HTTP version policy:
1 - RequestVersionExact (forces the request to use the specified HTTP version)
2 - RequestVersionOrHigher (tries the specified version or higher if supported)
3 - RequestVersionOrLower (tries the specified version or lower if necessary)
2
Do you want to include the Upgrade header for h2c? (yes/no): no
Request Headers:
An error occurred: The HTTP/2 server closed the connection. HTTP/2 error code 'HTTP_1_1_REQUIRED' (0xd).  (HttpProtocolError)
Ниже приведен мой http-клиент, если вы хотите использовать его для тестирования, и выше я выбрал мой вариант

Код: Выделить всё

using System;
using System.Net.Http;
using System.Threading.Tasks;

class Program
{
static async Task Main(string[] args)
{
string userInput;
do
{
// Prompt the user to specify the port number
Console.Write("Enter the server port (default is 5004): ");
string portInput = Console.ReadLine()?.Trim();
int port = string.IsNullOrEmpty(portInput) ? 5004 : int.Parse(portInput);

Console.Write("Enter Schema: (http, https): ");
string? schema = Console.ReadLine()?.Trim();

// Prompt the user to specify the HTTP version
Console.WriteLine("Select the HTTP version:");
Console.WriteLine("1 - HTTP/1.1");
Console.WriteLine("2 - HTTP/2");
Console.WriteLine("3 - HTTP/3 (if supported)");

Version httpVersion = new Version(2, 0); // Default to HTTP/2
string versionInput = Console.ReadLine()?.Trim();
switch (versionInput)
{
case "1":
httpVersion = new Version(1, 1);
break;
case "2":
httpVersion = new Version(2, 0);
break;
case "3":
httpVersion = new Version(3, 0); // Only if HTTP/3 is supported
break;
default:
Console.WriteLine("Invalid selection, using default: HTTP/2.");
break;
}

// Prompt the user to specify the HttpVersionPolicy
Console.WriteLine("Select the HTTP version policy:");
Console.WriteLine("1 - RequestVersionExact (forces the request to use the specified HTTP version)");
Console.WriteLine("2 - RequestVersionOrHigher (tries the specified version or higher if supported)");
Console.WriteLine("3 - RequestVersionOrLower (tries the specified version or lower if necessary)");

HttpVersionPolicy versionPolicy = HttpVersionPolicy.RequestVersionOrLower; // Default policy
string policyInput = Console.ReadLine()?.Trim();
switch (policyInput)
{
case "1":
versionPolicy = HttpVersionPolicy.RequestVersionExact;
break;
case "2":
versionPolicy = HttpVersionPolicy.RequestVersionOrHigher;
break;
case "3":
versionPolicy = HttpVersionPolicy.RequestVersionOrLower;
break;
default:
Console.WriteLine("Invalid selection, using default: RequestVersionOrLower.");
break;
}

// Ask the user if they want to include the Upgrade header for HTTP/2 cleartext (h2c)
bool includeUpgradeHeader = false;
if (httpVersion == new Version(2, 0) && schema == "http")
{
Console.Write("Do you want to include the Upgrade header for h2c? (yes/no): ");
string? upgradeHeaderInput = Console.ReadLine()?.Trim().ToLower();
includeUpgradeHeader = (upgradeHeaderInput == "yes");
}

// Create a SocketsHttpHandler and configure it for HTTP/2 Cleartext (h2c)
var handler = new SocketsHttpHandler
{
// Disable SSL/TLS (Cleartext connection)
SslOptions = { RemoteCertificateValidationCallback = (sender, cert, chain, sslPolicyErrors) =>  true }
};

// Set up HttpClient with the handler
using var client = new HttpClient(handler);

try
{
// Configure the request URL based on the specified port
string url = $"{schema ?? "http"}://localhost:{port}/";

// Configure the request to use the user-specified HTTP version
var request = new HttpRequestMessage(HttpMethod.Get, url)
{
Version = httpVersion, // Use the HTTP version specified by the user
VersionPolicy = versionPolicy  // Use the policy specified by the user
};

// Add the Upgrade header for HTTP/2 cleartext (h2c) if the user chooses to
if (includeUpgradeHeader)
{
request.Headers.Connection.Add("Upgrade");
request.Headers.Upgrade.Add(new System.Net.Http.Headers.ProductHeaderValue("h2"));
// Base64url-encoded empty SETTINGS frame for HTTP/2. (An actual encoded frame would be used in real apps)
request.Headers.Add("HTTP2-Settings", "AAMAAABkAAQAAP__");
}

// Print request headers
Console.WriteLine("Request Headers:");
foreach (var header in request.Headers)
{
Console.WriteLine($"{header.Key}: {string.Join(", ", header.Value)}");
}

// Send the request
var response = await client.SendAsync(request);

// Read the response content
var content = await response.Content.ReadAsStringAsync();

// Output the response status and content
Console.WriteLine($"\nStatus Code: {response.StatusCode}");
Console.WriteLine($"\nResponse Headers: {response.Headers} {response.Content.Headers}");
Console.WriteLine($"Response: {content}");
}
catch (Exception ex)
{
Console.WriteLine($"An error occurred: {ex.Message}");
}

Console.Write("Enter 'exit' to quit or press Enter to send a request: ");
userInput = Console.ReadLine()?.Trim();
} while (userInput?.ToLower() != "exit");
}
}
Почему для подключения через http требуется http 1_1?
Если я использую https, все работает нормально!
Если я выберу RequestVersionOrLower, он автоматически по умолчанию будет использовать http 1.1, поэтому, если это так, то какая польза от установки ListenOptions.Protocols в HttpProtocols.Http1AndHttp2AndHttp3, если по умолчанию всегда будет http 1.1 вместо http?
Это ограничение?

Подробнее здесь: https://stackoverflow.com/questions/791 ... -over-http
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»