This is an automated email from the ASF dual-hosted git repository.

pjfanning pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/pekko-http.git


The following commit(s) were added to refs/heads/main by this push:
     new 46b65143c Document selective WebSocket compression behavior #61 (#1175)
46b65143c is described below

commit 46b65143c2b2945b50a0b2e7b082e918108e1b98
Author: Matthias Kurz <[email protected]>
AuthorDate: Fri Jul 24 17:28:20 2026 +0200

    Document selective WebSocket compression behavior #61 (#1175)
    
    Clarify selector invocation, fragmentation, failure, and streaming 
semantics across the Scala and Java APIs and directive documentation.
---
 .../handleWebSocketMessages.md                     |  7 +++-
 .../handleWebSocketMessagesForOptionalProtocol.md  |  7 +++-
 .../handleWebSocketMessagesForProtocol.md          |  7 +++-
 .../http/javadsl/model/ws/WebSocketUpgrade.scala   | 44 ++++++++++++++++------
 .../http/scaladsl/model/ws/WebSocketUpgrade.scala  | 40 ++++++++++++++------
 .../server/directives/WebSocketDirectives.scala    | 10 ++++-
 .../server/directives/WebSocketDirectives.scala    | 15 ++++++--
 7 files changed, 99 insertions(+), 31 deletions(-)

diff --git 
a/docs/src/main/paradox/routing-dsl/directives/websocket-directives/handleWebSocketMessages.md
 
b/docs/src/main/paradox/routing-dsl/directives/websocket-directives/handleWebSocketMessages.md
index fb675362f..e153037b8 100644
--- 
a/docs/src/main/paradox/routing-dsl/directives/websocket-directives/handleWebSocketMessages.md
+++ 
b/docs/src/main/paradox/routing-dsl/directives/websocket-directives/handleWebSocketMessages.md
@@ -14,7 +14,12 @@ The directive first checks if the request was a valid 
WebSocket handshake reques
 with the passed handler. Otherwise, the request is rejected with an 
@apidoc[ExpectedWebSocketRequestRejection$].
 
 The overload that accepts a `shouldCompress` filter can select compression 
separately for each outbound message after
-`permessage-deflate` is negotiated.
+`permessage-deflate` is negotiated. It is evaluated synchronously once for 
each outbound text or binary message, and
+its result applies to every fragment of that message. The filter is not 
invoked for control frames or when compression
+was not negotiated. It should be fast and non-blocking; throwing from it fails 
the WebSocket stream.
+
+For a streamed message, the complete payload and its final size are not 
available when the filter is evaluated.
+Applications that select compression based on message size therefore need an 
explicit policy for streamed messages.
 
 WebSocket subprotocols offered in the `Sec-WebSocket-Protocol` header of the 
request are ignored. If you want to
 support several protocols use the 
@ref[handleWebSocketMessagesForProtocol](handleWebSocketMessagesForProtocol.md) 
directive, instead.
diff --git 
a/docs/src/main/paradox/routing-dsl/directives/websocket-directives/handleWebSocketMessagesForOptionalProtocol.md
 
b/docs/src/main/paradox/routing-dsl/directives/websocket-directives/handleWebSocketMessagesForOptionalProtocol.md
index 40f4222ed..804f01399 100644
--- 
a/docs/src/main/paradox/routing-dsl/directives/websocket-directives/handleWebSocketMessagesForOptionalProtocol.md
+++ 
b/docs/src/main/paradox/routing-dsl/directives/websocket-directives/handleWebSocketMessagesForOptionalProtocol.md
@@ -19,7 +19,12 @@ announced in the WebSocket request) @scala[contains 
`protocol`]@java[matches the
 the request is rejected with an 
@apidoc[UnsupportedWebSocketSubprotocolRejection].
 
 The overload that accepts a `shouldCompress` filter can select compression 
separately for each outbound message after
-`permessage-deflate` is negotiated.
+`permessage-deflate` is negotiated. It is evaluated synchronously once for 
each outbound text or binary message, and
+its result applies to every fragment of that message. The filter is not 
invoked for control frames or when compression
+was not negotiated. It should be fast and non-blocking; throwing from it fails 
the WebSocket stream.
+
+For a streamed message, the complete payload and its final size are not 
available when the filter is evaluated.
+Applications that select compression based on message size therefore need an 
explicit policy for streamed messages.
 
 To support several subprotocols you may chain several 
`handleWebSocketMessagesForOptionalProtocol` routes.
 
diff --git 
a/docs/src/main/paradox/routing-dsl/directives/websocket-directives/handleWebSocketMessagesForProtocol.md
 
b/docs/src/main/paradox/routing-dsl/directives/websocket-directives/handleWebSocketMessagesForProtocol.md
index 0664a1fba..bf04c7bea 100644
--- 
a/docs/src/main/paradox/routing-dsl/directives/websocket-directives/handleWebSocketMessagesForProtocol.md
+++ 
b/docs/src/main/paradox/routing-dsl/directives/websocket-directives/handleWebSocketMessagesForProtocol.md
@@ -19,7 +19,12 @@ subprotocol name. If yes, the directive completes the 
request with the passed ha
 either rejected with an @apidoc[ExpectedWebSocketRequestRejection$] or an 
@apidoc[UnsupportedWebSocketSubprotocolRejection].
 
 The overload that accepts a `shouldCompress` filter can select compression 
separately for each outbound message after
-`permessage-deflate` is negotiated.
+`permessage-deflate` is negotiated. It is evaluated synchronously once for 
each outbound text or binary message, and
+its result applies to every fragment of that message. The filter is not 
invoked for control frames or when compression
+was not negotiated. It should be fast and non-blocking; throwing from it fails 
the WebSocket stream.
+
+For a streamed message, the complete payload and its final size are not 
available when the filter is evaluated.
+Applications that select compression based on message size therefore need an 
explicit policy for streamed messages.
 
 To support several subprotocols, for example at the same path, several 
instances of `handleWebSocketMessagesForProtocol` can
 be chained using `~` as you can see in the below example.
diff --git 
a/http-core/src/main/scala/org/apache/pekko/http/javadsl/model/ws/WebSocketUpgrade.scala
 
b/http-core/src/main/scala/org/apache/pekko/http/javadsl/model/ws/WebSocketUpgrade.scala
index 04694d8df..c70b3edb1 100644
--- 
a/http-core/src/main/scala/org/apache/pekko/http/javadsl/model/ws/WebSocketUpgrade.scala
+++ 
b/http-core/src/main/scala/org/apache/pekko/http/javadsl/model/ws/WebSocketUpgrade.scala
@@ -57,9 +57,14 @@ trait WebSocketUpgrade {
    * Returns a response that can be used to answer a WebSocket handshake 
request. The connection will afterwards
    * use the given handlerFlow to handle WebSocket messages from the client.
    *
-   * If {@code permessage-deflate} is negotiated, {@code shouldCompress} is 
evaluated once for each outbound text or
-   * binary message. Returning {@code true} compresses that message and 
returning {@code false} sends it uncompressed.
-   * The filter does not affect inbound messages or whether compression is 
negotiated.
+   * If {@code permessage-deflate} is negotiated, {@code shouldCompress} is 
evaluated synchronously once for each
+   * outbound text or binary message. The result applies to every fragment of 
that message. Returning {@code true}
+   * compresses the message and returning {@code false} sends it uncompressed. 
The filter is not invoked for control
+   * frames or when compression was not negotiated, and it does not affect 
inbound messages or whether compression is
+   * negotiated.
+   *
+   * The filter should be fast and non-blocking; if it throws, the WebSocket 
stream fails. For streamed messages, the
+   * complete payload and its final size are not available when the filter is 
evaluated.
    *
    * @since 2.0.0
    */
@@ -93,9 +98,14 @@ trait WebSocketUpgrade {
    * use the given handlerFlow to handle WebSocket messages from the client. 
The given subprotocol must be one
    * of the ones offered by the client.
    *
-   * If {@code permessage-deflate} is negotiated, {@code shouldCompress} is 
evaluated once for each outbound text or
-   * binary message. Returning {@code true} compresses that message and 
returning {@code false} sends it uncompressed.
-   * The filter does not affect inbound messages or whether compression is 
negotiated.
+   * If {@code permessage-deflate} is negotiated, {@code shouldCompress} is 
evaluated synchronously once for each
+   * outbound text or binary message. The result applies to every fragment of 
that message. Returning {@code true}
+   * compresses the message and returning {@code false} sends it uncompressed. 
The filter is not invoked for control
+   * frames or when compression was not negotiated, and it does not affect 
inbound messages or whether compression is
+   * negotiated.
+   *
+   * The filter should be fast and non-blocking; if it throws, the WebSocket 
stream fails. For streamed messages, the
+   * complete payload and its final size are not available when the filter is 
evaluated.
    *
    * @since 2.0.0
    */
@@ -128,9 +138,14 @@ trait WebSocketUpgrade {
    * use the given inSink to handle WebSocket messages from the client and the 
given outSource to send messages to the
    * client.
    *
-   * If {@code permessage-deflate} is negotiated, {@code shouldCompress} is 
evaluated once for each outbound text or
-   * binary message. Returning {@code true} compresses that message and 
returning {@code false} sends it uncompressed.
-   * The filter does not affect inbound messages or whether compression is 
negotiated.
+   * If {@code permessage-deflate} is negotiated, {@code shouldCompress} is 
evaluated synchronously once for each
+   * outbound text or binary message. The result applies to every fragment of 
that message. Returning {@code true}
+   * compresses the message and returning {@code false} sends it uncompressed. 
The filter is not invoked for control
+   * frames or when compression was not negotiated, and it does not affect 
inbound messages or whether compression is
+   * negotiated.
+   *
+   * The filter should be fast and non-blocking; if it throws, the WebSocket 
stream fails. For streamed messages, the
+   * complete payload and its final size are not available when the filter is 
evaluated.
    *
    * @since 2.0.0
    */
@@ -166,9 +181,14 @@ trait WebSocketUpgrade {
    * use the given inSink to handle WebSocket messages from the client and the 
given outSource to send messages to the
    * client. The given subprotocol must be one of the ones offered by the 
client.
    *
-   * If {@code permessage-deflate} is negotiated, {@code shouldCompress} is 
evaluated once for each outbound text or
-   * binary message. Returning {@code true} compresses that message and 
returning {@code false} sends it uncompressed.
-   * The filter does not affect inbound messages or whether compression is 
negotiated.
+   * If {@code permessage-deflate} is negotiated, {@code shouldCompress} is 
evaluated synchronously once for each
+   * outbound text or binary message. The result applies to every fragment of 
that message. Returning {@code true}
+   * compresses the message and returning {@code false} sends it uncompressed. 
The filter is not invoked for control
+   * frames or when compression was not negotiated, and it does not affect 
inbound messages or whether compression is
+   * negotiated.
+   *
+   * The filter should be fast and non-blocking; if it throws, the WebSocket 
stream fails. For streamed messages, the
+   * complete payload and its final size are not available when the filter is 
evaluated.
    *
    * @since 2.0.0
    */
diff --git 
a/http-core/src/main/scala/org/apache/pekko/http/scaladsl/model/ws/WebSocketUpgrade.scala
 
b/http-core/src/main/scala/org/apache/pekko/http/scaladsl/model/ws/WebSocketUpgrade.scala
index 2f60e6c9f..779e40d1d 100644
--- 
a/http-core/src/main/scala/org/apache/pekko/http/scaladsl/model/ws/WebSocketUpgrade.scala
+++ 
b/http-core/src/main/scala/org/apache/pekko/http/scaladsl/model/ws/WebSocketUpgrade.scala
@@ -75,9 +75,13 @@ trait WebSocketUpgrade extends jm.ws.WebSocketUpgrade {
   /**
    * The high-level interface to create a WebSocket server based on "messages".
    *
-   * If `permessage-deflate` is negotiated, `shouldCompress` is evaluated once 
for each outbound text or binary
-   * message. Returning `true` compresses that message and returning `false` 
sends it uncompressed. The filter does not
-   * affect inbound messages or whether compression is negotiated.
+   * If `permessage-deflate` is negotiated, `shouldCompress` is evaluated 
synchronously once for each outbound text or
+   * binary message. The result applies to every fragment of that message. 
Returning `true` compresses the message and
+   * returning `false` sends it uncompressed. The filter is not invoked for 
control frames or when compression was not
+   * negotiated, and it does not affect inbound messages or whether 
compression is negotiated.
+   *
+   * The filter should be fast and non-blocking; if it throws, the WebSocket 
stream fails. For streamed messages, the
+   * complete payload and its final size are not available when the filter is 
evaluated.
    *
    * @since 2.0.0
    */
@@ -90,9 +94,13 @@ trait WebSocketUpgrade extends jm.ws.WebSocketUpgrade {
    * The high-level interface to create a WebSocket server based on "messages".
    *
    * Optionally, a subprotocol out of the ones requested by the client can be 
chosen. If `permessage-deflate` is
-   * negotiated, `shouldCompress` is evaluated once for each outbound text or 
binary message. Returning `true`
-   * compresses that message and returning `false` sends it uncompressed. The 
filter does not affect inbound messages
-   * or whether compression is negotiated.
+   * negotiated, `shouldCompress` is evaluated synchronously once for each 
outbound text or binary message. The result
+   * applies to every fragment of that message. Returning `true` compresses 
the message and returning `false` sends it
+   * uncompressed. The filter is not invoked for control frames or when 
compression was not negotiated, and it does not
+   * affect inbound messages or whether compression is negotiated.
+   *
+   * The filter should be fast and non-blocking; if it throws, the WebSocket 
stream fails. For streamed messages, the
+   * complete payload and its final size are not available when the filter is 
evaluated.
    *
    * @since 2.0.0
    */
@@ -142,9 +150,13 @@ trait WebSocketUpgrade extends jm.ws.WebSocketUpgrade {
   /**
    * The high-level interface to create a WebSocket server based on "messages".
    *
-   * If `permessage-deflate` is negotiated, `shouldCompress` is evaluated once 
for each outbound text or binary
-   * message. Returning `true` compresses that message and returning `false` 
sends it uncompressed. The filter does not
-   * affect inbound messages or whether compression is negotiated.
+   * If `permessage-deflate` is negotiated, `shouldCompress` is evaluated 
synchronously once for each outbound text or
+   * binary message. The result applies to every fragment of that message. 
Returning `true` compresses the message and
+   * returning `false` sends it uncompressed. The filter is not invoked for 
control frames or when compression was not
+   * negotiated, and it does not affect inbound messages or whether 
compression is negotiated.
+   *
+   * The filter should be fast and non-blocking; if it throws, the WebSocket 
stream fails. For streamed messages, the
+   * complete payload and its final size are not available when the filter is 
evaluated.
    *
    * @since 2.0.0
    */
@@ -158,9 +170,13 @@ trait WebSocketUpgrade extends jm.ws.WebSocketUpgrade {
    * The high-level interface to create a WebSocket server based on "messages".
    *
    * Optionally, a subprotocol out of the ones requested by the client can be 
chosen. If `permessage-deflate` is
-   * negotiated, `shouldCompress` is evaluated once for each outbound text or 
binary message. Returning `true`
-   * compresses that message and returning `false` sends it uncompressed. The 
filter does not affect inbound messages
-   * or whether compression is negotiated.
+   * negotiated, `shouldCompress` is evaluated synchronously once for each 
outbound text or binary message. The result
+   * applies to every fragment of that message. Returning `true` compresses 
the message and returning `false` sends it
+   * uncompressed. The filter is not invoked for control frames or when 
compression was not negotiated, and it does not
+   * affect inbound messages or whether compression is negotiated.
+   *
+   * The filter should be fast and non-blocking; if it throws, the WebSocket 
stream fails. For streamed messages, the
+   * complete payload and its final size are not available when the filter is 
evaluated.
    *
    * @since 2.0.0
    */
diff --git 
a/http/src/main/scala/org/apache/pekko/http/javadsl/server/directives/WebSocketDirectives.scala
 
b/http/src/main/scala/org/apache/pekko/http/javadsl/server/directives/WebSocketDirectives.scala
index d4a1c9097..7c568dc74 100644
--- 
a/http/src/main/scala/org/apache/pekko/http/javadsl/server/directives/WebSocketDirectives.scala
+++ 
b/http/src/main/scala/org/apache/pekko/http/javadsl/server/directives/WebSocketDirectives.scala
@@ -62,6 +62,9 @@ abstract class WebSocketDirectives extends SecurityDirectives 
{
   /**
    * Handles WebSocket requests with the given handler and selectively 
compresses outbound messages for which
    * {@code shouldCompress} returns {@code true} when {@code 
permessage-deflate} was negotiated.
+   * The filter is evaluated synchronously once per outbound text or binary 
message, and the result applies to all
+   * fragments. It should be fast and non-blocking; if it throws, the 
WebSocket stream fails. A streamed message's
+   * complete payload and final size are not available when the filter is 
evaluated.
    *
    * @since 2.0.0
    */
@@ -82,7 +85,9 @@ abstract class WebSocketDirectives extends SecurityDirectives 
{
   /**
    * Handles WebSocket requests with the given handler if the given 
subprotocol is offered and selectively compresses
    * outbound messages for which {@code shouldCompress} returns {@code true} 
when {@code permessage-deflate} was
-   * negotiated.
+   * negotiated. The filter is evaluated synchronously once per outbound text 
or binary message, and the result applies
+   * to all fragments. It should be fast and non-blocking; if it throws, the 
WebSocket stream fails. A streamed
+   * message's complete payload and final size are not available when the 
filter is evaluated.
    *
    * @since 2.0.0
    */
@@ -113,6 +118,9 @@ abstract class WebSocketDirectives extends 
SecurityDirectives {
   /**
    * Handles WebSocket requests with the given handler and selectively 
compresses outbound messages for which
    * {@code shouldCompress} returns {@code true} when {@code 
permessage-deflate} was negotiated.
+   * The filter is evaluated synchronously once per outbound text or binary 
message, and the result applies to all
+   * fragments. It should be fast and non-blocking; if it throws, the 
WebSocket stream fails. A streamed message's
+   * complete payload and final size are not available when the filter is 
evaluated.
    *
    * @since 2.0.0
    */
diff --git 
a/http/src/main/scala/org/apache/pekko/http/scaladsl/server/directives/WebSocketDirectives.scala
 
b/http/src/main/scala/org/apache/pekko/http/scaladsl/server/directives/WebSocketDirectives.scala
index 5730ab568..6ebb88506 100644
--- 
a/http/src/main/scala/org/apache/pekko/http/scaladsl/server/directives/WebSocketDirectives.scala
+++ 
b/http/src/main/scala/org/apache/pekko/http/scaladsl/server/directives/WebSocketDirectives.scala
@@ -62,7 +62,10 @@ trait WebSocketDirectives {
 
   /**
    * Handles WebSocket requests with the given handler and selectively 
compresses outbound messages for which
-   * `shouldCompress` returns `true` when `permessage-deflate` was negotiated.
+   * `shouldCompress` returns `true` when `permessage-deflate` was negotiated. 
The filter is evaluated synchronously
+   * once per outbound text or binary message, and the result applies to all 
fragments. It should be fast and
+   * non-blocking; if it throws, the WebSocket stream fails. A streamed 
message's complete payload and final size are
+   * not available when the filter is evaluated.
    *
    * @group websocket
    * @since 2.0.0
@@ -83,7 +86,10 @@ trait WebSocketDirectives {
 
   /**
    * Handles WebSocket requests with the given handler if the given 
subprotocol is offered and selectively compresses
-   * outbound messages for which `shouldCompress` returns `true` when 
`permessage-deflate` was negotiated.
+   * outbound messages for which `shouldCompress` returns `true` when 
`permessage-deflate` was negotiated. The filter
+   * is evaluated synchronously once per outbound text or binary message, and 
the result applies to all fragments. It
+   * should be fast and non-blocking; if it throws, the WebSocket stream 
fails. A streamed message's complete payload
+   * and final size are not available when the filter is evaluated.
    *
    * @group websocket
    * @since 2.0.0
@@ -118,7 +124,10 @@ trait WebSocketDirectives {
 
   /**
    * Handles WebSocket requests with the given handler and selectively 
compresses outbound messages for which
-   * `shouldCompress` returns `true` when `permessage-deflate` was negotiated.
+   * `shouldCompress` returns `true` when `permessage-deflate` was negotiated. 
The filter is evaluated synchronously
+   * once per outbound text or binary message, and the result applies to all 
fragments. It should be fast and
+   * non-blocking; if it throws, the WebSocket stream fails. A streamed 
message's complete payload and final size are
+   * not available when the filter is evaluated.
    *
    * @group websocket
    * @since 2.0.0


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to