Skip to content

Conversation

Copy link

Copilot AI commented Jul 26, 2025

Thanks for asking me to work on this. I will get started on it and keep this PR's description up to date as I form a plan and make progress.

Original description:

Problem

SignalR client throws an exception when trying to connect to HTTP/2 servers with SkipNegotiation = true:

An HttpMessageInvoker instance must be passed to ConnectAsync when using HTTP/2. (Parameter 'options')

Root Cause

In WebSocketsTransport.DefaultWebSocketFactory, the allowHttp2 variable is set to false when authentication methods like Negotiate Auth are used. However, this logic doesn't account for scenarios where SkipNegotiation = true, which bypasses the authentication negotiation entirely.

When allowHttp2 = false, the code path that passes the HttpClient as an invoker to ConnectAsync is skipped, causing the HTTP/2 connection to fail.

Solution

Modify the logic in DefaultWebSocketFactory to allow HTTP/2 when SkipNegotiation = true, even if other authentication methods would normally disable it. When negotiation is skipped, authentication concerns don't apply, so HTTP/2 should be allowed.

Changes Required

  1. Update the condition that sets allowHttp2 = false to check if negotiation is being skipped
  2. When SkipNegotiation = true, allow HTTP/2 connections regardless of authentication configuration

Test Case

The fix should allow this code to work without throwing an exception:

await using var connection = new HubConnectionBuilder()
    .WithUrl("http://localhost:5001/hub/hello", options =>
    {
        options.SkipNegotiation = true;
        options.Transports = HttpTransportType.WebSockets;
        options.WebSocketConfiguration = clientWebSocketOptions =>
        {
            clientWebSocketOptions.HttpVersion = HttpVersion.Version20;
            clientWebSocketOptions.HttpVersionPolicy = HttpVersionPolicy.RequestVersionOrLower;
        };
    })
    .Build();

await connection.StartAsync();

Related Issue

Fixes dotnet#59303

This pull request was created as a result of the following prompt from Copilot chat.

Problem

SignalR client throws an exception when trying to connect to HTTP/2 servers with SkipNegotiation = true:

An HttpMessageInvoker instance must be passed to ConnectAsync when using HTTP/2. (Parameter 'options')

Root Cause

In WebSocketsTransport.DefaultWebSocketFactory, the allowHttp2 variable is set to false when authentication methods like Negotiate Auth are used. However, this logic doesn't account for scenarios where SkipNegotiation = true, which bypasses the authentication negotiation entirely.

When allowHttp2 = false, the code path that passes the HttpClient as an invoker to ConnectAsync is skipped, causing the HTTP/2 connection to fail.

Solution

Modify the logic in DefaultWebSocketFactory to allow HTTP/2 when SkipNegotiation = true, even if other authentication methods would normally disable it. When negotiation is skipped, authentication concerns don't apply, so HTTP/2 should be allowed.

Changes Required

  1. Update the condition that sets allowHttp2 = false to check if negotiation is being skipped
  2. When SkipNegotiation = true, allow HTTP/2 connections regardless of authentication configuration

Test Case

The fix should allow this code to work without throwing an exception:

await using var connection = new HubConnectionBuilder()
    .WithUrl("http://localhost:5001/hub/hello", options =>
    {
        options.SkipNegotiation = true;
        options.Transports = HttpTransportType.WebSockets;
        options.WebSocketConfiguration = clientWebSocketOptions =>
        {
            clientWebSocketOptions.HttpVersion = HttpVersion.Version20;
            clientWebSocketOptions.HttpVersionPolicy = HttpVersionPolicy.RequestVersionOrLower;
        };
    })
    .Build();

await connection.StartAsync();

Related Issue

Fixes dotnet#59303


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

@WeihanLi WeihanLi closed this Jul 26, 2025
@WeihanLi WeihanLi deleted the copilot/fix-d374b9e9-ff4f-4e3a-af69-a0a125c05045 branch July 26, 2025 08:16
Copilot AI requested a review from WeihanLi July 26, 2025 08:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SignalR Error when connect to http2 server with SkipNegotiation

2 participants