mkurz opened a new pull request, #1114:
URL: https://github.com/apache/pekko-http/pull/1114
## What changed
Adds server-side support for RFC 7692 `permessage-deflate` WebSocket
compression.
Compression is negotiated during the WebSocket handshake when the client
offers `permessage-deflate` in `Sec-WebSocket-Extensions`. It is enabled by
default and can be disabled globally through configuration.
Also adds an API option to decline negotiated compression for a single
accepted WebSocket upgrade.
Fixes #61.
## Details
This PR adds:
- `permessage-deflate` negotiation for server-side WebSockets
- inbound compressed message inflation
- outbound message deflation
- fragmented compressed message handling
- context takeover and no-context-takeover negotiation
- configurable compression level
- configurable max decompressed allocation
- configurable preferred `client_max_window_bits`
- per-upgrade compression disabling via new `WebSocketUpgrade` overloads
- documentation, reference config, release notes, and MiMa filters
## Netty comparison
The implementation follows Netty’s `permessage-deflate` behavior where it
makes sense for Pekko HTTP:
- compressed inbound messages are inflated before they reach the application
- outbound text/binary messages are compressed when compression was
negotiated
- fragmented compressed messages keep RSV1 only on the first frame
- control frames can be interleaved with fragmented compressed messages
- context takeover is retained by default
- `server_no_context_takeover` and `client_no_context_takeover` can be
negotiated
- `client_max_window_bits` can be negotiated
- decompressed output is bounded through `max-allocation`
One deliberate difference is zlib implementation scope. Netty also uses the
JDK `Deflater` and `Inflater` APIs for the default zlib settings, and only
switches to JZlib when non-default zlib `windowBits` or `memLevel` support is
needed. Pekko HTTP currently uses only the JDK `Deflater` and `Inflater` APIs,
like Tomcat and Jetty. The JDK API does not expose zlib `windowBits` or
`memLevel`, so Pekko HTTP does not accept `server_max_window_bits` values below
`15` and does not provide server window-size or memory-level settings.
Clients may still request `client_max_window_bits`; when they do, Pekko HTTP
can include the configured `preferred-client-window-size` in the handshake
response to ask the client to use that window size for client-to-server
messages.
## Security notes
WebSocket compression can increase CPU and memory usage, and compression can
be problematic when messages include secrets alongside attacker-controlled data.
The default context takeover settings match common server defaults and favor
compression efficiency. Applications that need a more conservative setup can
configure no-context-takeover behavior or disable compression globally/per
accepted WebSocket.
`max-allocation` limits decompressed message size. If the limit is exceeded
while inflating a compressed message, Pekko HTTP closes the connection with a
WebSocket protocol error.
## Testing
Ran:
```bash
sbt "http-core / Test / testOnly
org.apache.pekko.http.impl.engine.ws.WebSocketServerSpec"
sbt +mimaReportBinaryIssues
```
Also verified Play Framework integration against the locally published Pekko
HTTP artifact:
(This is a WIP pull request for Play which I will submit tomorrow - I will
you ping you then)
```bash
sbt -Dpekko.http.version=<local-version> \
"Play-Integration-Test / Test / testOnly
play.it.http.websocket.PekkoHttpWebSocketCompressionSpec"
sbt -Dpekko.http.version=<local-version> \
"Play-Integration-Test / Test / testOnly
play.it.http.websocket.PekkoHttpWebSocketSpec"
```
## References
- https://github.com/playframework/playframework/issues/4186
- https://github.com/akka/akka-http/issues/659
- https://github.com/playframework/playframework/issues/10863
- https://github.com/playframework/playframework/pull/11169
- https://github.com/playframework/playframework/pull/12477
- https://github.com/playframework/netty-reactive-streams/pull/126
- https://github.com/apache/pekko-http/issues/61
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]