Inconsistency between IIS and Kestrel for websocket connect operation with duplicate 'Upgrade: websocket, websocket' header
- Dominant language
- C#
- Stars
- 38.4k
- Forks
- 10.9k
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 290
Description
### Is there an existing issue for this?
- [X] I have searched the existing issues
### Describe the bug
Accidentally I've sent a websocket connect request with duplicate `websocket` header like here:

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`

- 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:
- [run WebApp](https://github.com/DeagleGross/repro-1/tree/main/WebApp/WebApp)
- [run client](https://github.com/DeagleGross/repro-1/tree/main/WebApp/Client)
### 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.$(String[] args) in C:\code\personal\repro-1\WebApp\Client\Program.cs:line 10
at Program.(String[] args)
```
### .NET Version
net6.0 (local 6.0.316)
### Anything else?
_No response_
Contributor guide
Assessment
This issue has not been assessed yet.