Skip to content

Fix WebSocket handshake failure for chargers missing Connection: Upgrade header#1984

Open
vavallee wants to merge 5 commits into
lbbrhzn:mainfrom
vavallee:fix/autel-connection-header-v0.10.15
Open

Fix WebSocket handshake failure for chargers missing Connection: Upgrade header#1984
vavallee wants to merge 5 commits into
lbbrhzn:mainfrom
vavallee:fix/autel-connection-header-v0.10.15

Conversation

@vavallee

@vavallee vavallee commented Jun 27, 2026

Copy link
Copy Markdown

Problem

Some charger firmware (e.g. Autel MaxiCharger US AC LW10-N14, fw v1.38.00/v1.22.00) omits the required Connection: Upgrade header from the WebSocket opening handshake. websockets 14+ strictly validates this header and raises InvalidUpgrade, so the affected chargers can never connect to the OCPP central system.

Fix

Add a process_request hook (_fix_missing_connection_header) that injects Connection: upgrade before the library validates the handshake, only when the header is absent. Logs a warning recommending a firmware update. No effect on compliant chargers (covered by a test asserting no warning is logged when the header is present).

Notes

Summary by CodeRabbit

  • Bug Fixes
    • Improved WebSocket connection handling for chargers with firmware that omits the required upgrade header.
    • Connection attempts that previously failed during the initial handshake should now proceed more reliably.
    • Added safeguards to preserve valid connection headers when they are already present.

vavallee and others added 4 commits June 27, 2026 20:46
…ade header

Some charger firmware (confirmed: Autel MaxiCharger US AC LW10-N14,
firmware v1.38.00 / v1.22.00) sends a WebSocket opening handshake
without the required `Connection: Upgrade` header.

websockets 14+ strictly enforces this header in `ServerProtocol.accept()`
and raises `InvalidUpgrade: missing Connection header`, causing the
handshake to fail and the charger to be permanently unable to connect.

Fix: add a `process_request` hook to the `websockets.serve()` call that
injects `Connection: upgrade` when the header is absent, before the
library's validation runs.  A warning is logged so operators are aware
and can chase a firmware update from the charger vendor.

(cherry picked from commit 0a7e855)
… unit tests

Makes the function directly importable for testing without needing to
instantiate CentralSystem or mock websockets.serve. Adds two async unit
tests: one verifying header injection + warning log when Connection is
absent, one verifying the header is left intact when already present.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
(cherry picked from commit 4729f1b)
test_fix_missing_connection_header_leaves_existing_intact claimed "no
warning is logged" in its docstring but never verified it. Added caplog
fixture, wrapped the call in caplog.at_level(WARNING), and asserted no
WARNING-level records were emitted.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
(cherry picked from commit 4247ac4)
Add missing blank lines after function definition (E302) and
restructure docstring to have a one-line summary (D205).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit bfdb4ee)
@coderabbitai

coderabbitai Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4827b755-9caf-4032-9554-38037ffa002f

📥 Commits

Reviewing files that changed from the base of the PR and between c61c1f4 and 9c709a6.

📒 Files selected for processing (2)
  • custom_components/ocpp/api.py
  • tests/test_api_paths.py

📝 Walkthrough

Walkthrough

Adds _fix_missing_connection_header, a process_request callback that detects missing Connection headers in WebSocket upgrade requests, logs a warning, and injects Connection: upgrade before validation. This callback is wired into websockets.serve. Two new async tests cover the injection and no-op paths.

Changes

WebSocket Connection header workaround

Layer / File(s) Summary
Header injection callback and server wiring
custom_components/ocpp/api.py
Imports Request/Response from websockets.http11, defines _fix_missing_connection_header to detect absent Connection headers, log a warning, and mutate headers to set Connection: upgrade, then wires it into websockets.serve via process_request.
Tests for injection and no-op
tests/test_api_paths.py
Adds _fix_missing_connection_header to test imports and introduces two async tests: one asserting warning emission and header injection when Connection is missing, one asserting no mutation and no warning when it is present.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐇 A header went missing, the handshake would fail,
So I twitched my nose and injected the trail.
"Connection: upgrade!" I whispered with care,
The websocket opened — no error to bear.
Two tests to confirm it, all passing with glee! 🌿

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: a WebSocket handshake fix for chargers missing the Connection: Upgrade header.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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.

1 participant