Skip to content

bugfix: client: reject a handshake response whose status is not 101 - #104

Merged
zhuizhuhaomeng merged 1 commit into
openresty:masterfrom
shreemaan-abhishek:bugfix/handshake-status
Aug 17, 2026
Merged

bugfix: client: reject a handshake response whose status is not 101#104
zhuizhuhaomeng merged 1 commit into
openresty:masterfrom
shreemaan-abhishek:bugfix/handshake-status

Conversation

@shreemaan-abhishek

Copy link
Copy Markdown
Contributor

What this fixes

client:connect() validates the handshake response with:

m, err = re_match(header, [[^\s*HTTP/1\.1\s+]], "jo")

Any HTTP/1.1 status line passes, so a server (or an intermediary that does not support Upgrade, e.g. a load balancer) answering 403, 301, or 502 is reported as a successfully connected WebSocket. The caller then writes masked frames into a plain HTTP connection and only finds out via garbage on the next recv_frame(), with no way to distinguish this from a transient network error and react (e.g. fall back to a non-WebSocket transport).

RFC 6455 section 4.1 requires the client to fail the connection whenever the handshake status is not 101.

Change

  • connect() now captures the status code and returns nil, "failed websocket handshake: unexpected response status: <code>", header for anything other than 101. The raw response header is still returned as the third value so callers can inspect the full response.
  • Added t/handshake.t: refused upgrade (403), redirect (301), and a success control against resty.websocket.server.

Fixes #47 (open since 2019, asking for exactly this check, at the FIXME: verify the response headers site).

Related: #94 adds an opt-in validate_handshake option as part of a larger feature. This PR is only the minimal always-on status check: treating a non-101 response as a connected WebSocket is never correct, so it should apply by default rather than behind a flag. Happy to rebase either way if the maintainers prefer the #94 approach.

Per RFC 6455 section 4.1, a status code other than 101 means the server
has not accepted the upgrade and the client must fail the connection.
connect() only checked that the status line starts with "HTTP/1.1", so
any plain HTTP response (403, 301, 502, ...) was reported as a successful
handshake and subsequent frames were written into a non-WebSocket
connection.

Fixes openresty#47.
@mergify

mergify Bot commented Aug 12, 2026

Copy link
Copy Markdown

Tick the box to add this pull request to the merge queue (same as @mergifyio queue).

  • Queue this pull request

@zhuizhuhaomeng
zhuizhuhaomeng merged commit 2606072 into openresty:master Aug 17, 2026
2 of 3 checks passed
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.

unexpected connection behavior

2 participants