Open
Description
Describe the bug
When the shouldUpgrade() closure in a webSocket route returns nil or throws an error, Vapor returns a zero length response.
Expected: When an attempt to open a WebSocket fails the server should send a 400 or 500 level HTTP response.
To Reproduce
- Add the following 3 lines to "routes.swift" in a template Vapor project created with
vapor new hello -n
.
app.webSocket("successsocket", shouldUpgrade: { req in return [:] }, onUpgrade: { req, socket in })
app.webSocket("failsocket", shouldUpgrade: { req in return nil }, onUpgrade: { req, socket in })
app.webSocket("throwsocket", shouldUpgrade: { req in throw Abort(.unauthorized) }, onUpgrade: { req, socket in })
- run curl, this opens a WebSocket connection:
curl --include \
--header "Connection: Upgrade" \
--header "Upgrade: websocket" \
--header "Host: 127.0.0.1" \
--header "Origin: http://127.0.0.1:8080" \
--header "Sec-WebSocket-Key: SGVsbG8sIHdvcmxkIQ==" \
--header "Sec-WebSocket-Version: 13" \
http://127.0.0.1:8080/successsocket
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Sec-WebSocket-Accept: qGEgH3En71di5rrssAZTmtRTyFk=
Connection: upgrade
date: Sat, 02 Mar 2024 23:18:56 GMT
^C
- run curl again, this time using the route that returns nil from shouldUpgrade():
curl --include \
--header "Connection: Upgrade" \
--header "Upgrade: websocket" \
--header "Host: 127.0.0.1" \
--header "Origin: http://127.0.0.1:8080" \
--header "Sec-WebSocket-Key: SGVsbG8sIHdvcmxkIQ==" \
--header "Sec-WebSocket-Version: 13" \
http://127.0.0.1:8080/failsocket
curl: (52) Empty reply from server
- And, with the route that throws a 401 Unauthorized error:
curl --include \
--header "Connection: Upgrade" \
--header "Upgrade: websocket" \
--header "Host: 127.0.0.1" \
--header "Origin: http://127.0.0.1:8080" \
--header "Sec-WebSocket-Key: SGVsbG8sIHdvcmxkIQ==" \
--header "Sec-WebSocket-Version: 13" \
http://127.0.0.1:8080/throwsocket
curl: (52) Empty reply from server
Expected behavior
I believe HTTP servers are always supposed to return at least a status line in responses. A zero-length response leaves clients no way to communicate why the WebSocket request failed.
Environment
- Vapor Framework version: "4.92.4"
- Vapor Toolbox version:
- OS version: 14.3.1 (23D60)
Additional context
These curl commands use http:// instead of ws:// to make it easy to show the issue. Note that the success case opens the socket and gives the proper 101 response.