Skip to content

Improve WebSocket compression internals and resource cleanup - #1173

Merged
pjfanning merged 3 commits into
apache:mainfrom
mkurz:websocket-review-feedback
Jul 23, 2026
Merged

Improve WebSocket compression internals and resource cleanup#1173
pjfanning merged 3 commits into
apache:mainfrom
mkurz:websocket-review-feedback

Conversation

@mkurz

@mkurz mkurz commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

This is a follow-up to

that addresses review feedback and improves the WebSocket compression implementation without changing its public API or configuration.

The changes:

  • Reuse 8 KiB buffers in the inflater and deflater flows instead of allocating a buffer for every operation.
  • Accumulate split physical-frame data without repeatedly copying previous fragments, then compact it once before compression or decompression.
  • Reject empty client_max_window_bits and server_max_window_bits values.
  • Handle custom WebSocketSettings implementations without an unsafe cast.
  • Process repeated Sec-WebSocket-Extensions headers directly.
  • Align the disabled compression settings with the reference.conf default for max-allocation.
  • Replace mutable global inflater/deflater test factories with factories scoped to each materialized flow.
  • Verify that every created Inflater and Deflater is released exactly once.

Resource cleanup is tested for normal completion, upstream failure, downstream cancellation, protocol errors, and incomplete compression state.

The wire and stream semantics for incomplete compressed messages intentionally remain unchanged. This follows Netty’s compression-layer behavior: incomplete codec state is discarded during connection termination while its resources are released. Any future change to truncated-message handling should be designed as a general WebSocket framing change covering both compressed and uncompressed messages.

Testing

  • WebSocketServerSpec
  • sbt applyCodeStyle
  • sbt checkCodeStyle
  • sbt +mimaReportBinaryIssues
  • sbt validatePullRequest

References

mkurz added 2 commits July 23, 2026 16:59
* Reuse 8 KiB buffers in the inflater and deflater flows.
* Accumulate split frame data without repeatedly copying earlier chunks.
* Handle extension parameters and custom WebSocket settings defensively.
* Simplify extension header handling and align disabled compression defaults.
* Inject inflater and deflater creation per materialized flow instead of using mutable global test hooks.
* Verify cleanup after completion, failure, cancellation, protocol errors, and incomplete frame or message state.
* Ensure every created compression resource is released exactly once.
Use the 256 KiB default agreed during review of the initial WebSocket compression implementation. Keep the disabled settings baseline aligned with reference.conf.
@mkurz

mkurz commented Jul 23, 2026

Copy link
Copy Markdown
Contributor Author

I also pushed commit which increases the default WebSocket decompression limit from 64 KiB to 256 KiB, as agreed during the review of #1114 (comment).
The commit updates both reference.conf and the internal disabled-settings baseline. The limit remains configurable, and setting it to 0 disables it.
For comparison, Netty exposes an equivalent maxAllocation setting but defaults it to 0 (unlimited). Pekko HTTP applies its limit cumulatively to the complete logical WebSocket message, including continuation frames.
The focused WebSocketServerSpec still passes with all 38 tests successful.

@pjfanning

Copy link
Copy Markdown
Member

lgtm

@pjfanning
pjfanning merged commit 6f5670f into apache:main Jul 23, 2026
6 checks passed
@mkurz
mkurz deleted the websocket-review-feedback branch July 23, 2026 21:31
@pjfanning pjfanning added this to the 2.0.0-M2 milestone Jul 24, 2026
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.

2 participants