dotnet/aspnetcore

Inconsistency between IIS and Kestrel for websocket connect operation with duplicate 'Upgrade: websocket, websocket' header

Open

#50,364 创建于 2023年8月28日

在 GitHub 查看
 (2 评论) (2 反应) (2 负责人)C# (10,653 fork)batch import
area-networkingbugfeature-iisfeature-websocketshelp wanted

仓库指标

Star
 (37,933 star)
PR 合并指标
 (平均合并 16天 9小时) (30 天内合并 258 个 PR)

描述

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

Accidentally I've sent a websocket connect request with duplicate websocket header like here: image

It worked on a Kestrel based app: websocket connection was established, and I could send \ receive messages and gracefully terminate a connection.

  • It failed on IIS hosted app: after calling context.WebSockets.AcceptWebSocketAsync() websocket.State is Open image
  • but client immediately disconnected:
Could not connect to ws://localhost:21156
12:00:24
Error: Unexpected server response: 101
Handshake Details
Request URL: http://localhost:21156/
Request Method: GET
Status Code: 101 Switching Protocols
Request Headers
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: gCyKijP/CPAUtW3Cjyf8gA==
Connection: Upgrade
Upgrade: websocket, websocket
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
Host: localhost:21156
Response Headers
Transfer-Encoding: chunked
Upgrade: websocket
Server: Microsoft-IIS/10.0
Sec-WebSocket-Accept: fiwTshwZAtNTY2V2+ynOPK4kFNk=
X-Powered-By: ASP.NET
Date: Mon, 28 Aug 2023 10:00:24 GMT

Expected Behavior

As per my understanding, either Kestrel implementation should fail as well, or IIS should handle duplicate Upgrade: websocket, websocket header. Let me know, if I am doing something wrong.

Steps To Reproduce

repro is as simple as creating an ASP.NET core project and using such setup in Program.cs:

app.UseWebSockets();
app.Use(async (context, next) =>
{
    if (context.WebSockets.IsWebSocketRequest)
    {
        using var webSocket = await context.WebSockets.AcceptWebSocketAsync();
        await Echo(webSocket);
    }
    else
    {
        await next(context);
    }
});

app.Run();

and make a websocket connect call with Upgrade: websocket, websocket header.

if you need a repro in a repository:

Exceptions (if any)

Unhandled exception. System.Net.WebSockets.WebSocketException (203): The server's response was missing the required header 'Connection'.
   at System.Net.WebSockets.WebSocketHandle.ValidateHeader(HttpHeaders headers, String name, String expectedValue)
   at System.Net.WebSockets.WebSocketHandle.ConnectAsync(Uri uri, CancellationToken cancellationToken, ClientWebSocketOptions options)
   at System.Net.WebSockets.ClientWebSocket.ConnectAsyncCore(Uri uri, CancellationToken cancellationToken)
   at Program.<Main>$(String[] args) in C:\code\personal\repro-1\WebApp\Client\Program.cs:line 10
   at Program.<Main>(String[] args)

.NET Version

net6.0 (local 6.0.316)

Anything else?

No response

贡献者指南