From dce940fb159f9a2b748ae0eb7bcb420a808e2e49 Mon Sep 17 00:00:00 2001 From: Georgios Andrianakis Date: Wed, 4 Jan 2023 18:08:33 +0200 Subject: [PATCH] Properly handle SSE comments in RESTEasy Reactive client and server code Fixes: #30169 --- .../reactive/server/test/stream/StreamResource.java | 3 ++- .../reactive/server/test/stream/StreamTestCase.java | 12 +++++++----- .../resteasy/reactive/client/impl/SseParser.java | 4 ++-- .../jboss/resteasy/reactive/server/core/SseUtil.java | 6 ++++-- 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/stream/StreamResource.java b/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/stream/StreamResource.java index 307d5b77d5d814..31f931789d3de7 100644 --- a/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/stream/StreamResource.java +++ b/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/stream/StreamResource.java @@ -160,7 +160,8 @@ public Multi sseThrows() { @GET @Produces(MediaType.SERVER_SENT_EVENTS) public Multi sseRaw(@Context Sse sse) { - return Multi.createFrom().items(sse.newEventBuilder().id("one").data("uno").name("eins").build(), + return Multi.createFrom().items(sse.newEventBuilder().comment("dummy").build(), + sse.newEventBuilder().id("one").data("uno").name("eins").build(), sse.newEventBuilder().id("two").data("dos").name("zwei").build(), sse.newEventBuilder().id("three").data("tres").name("drei").build()); } diff --git a/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/stream/StreamTestCase.java b/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/stream/StreamTestCase.java index d43b1ddb1249bd..f1615e674ad80b 100644 --- a/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/stream/StreamTestCase.java +++ b/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/stream/StreamTestCase.java @@ -3,7 +3,6 @@ import java.net.URI; import java.nio.charset.StandardCharsets; import java.time.Duration; -import java.util.Arrays; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CopyOnWriteArrayList; @@ -211,7 +210,7 @@ public void testSse() throws InterruptedException { }); sse.open(); Assertions.assertTrue(latch.await(20, TimeUnit.SECONDS)); - Assertions.assertEquals(Arrays.asList("a", "b", "c"), results); + org.assertj.core.api.Assertions.assertThat(results).containsExactly("a", "b", "c"); Assertions.assertEquals(0, errors.size()); } } @@ -248,7 +247,9 @@ public void testSseForMultiWithOutboundSseEvent() throws InterruptedException { List results = new CopyOnWriteArrayList<>(); List ids = new CopyOnWriteArrayList<>(); List names = new CopyOnWriteArrayList<>(); + List comments = new CopyOnWriteArrayList<>(); sse.register(event -> { + comments.add(event.getComment()); results.add(event.readData()); ids.add(event.getId()); names.add(event.getName()); @@ -259,9 +260,10 @@ public void testSseForMultiWithOutboundSseEvent() throws InterruptedException { }); sse.open(); Assertions.assertTrue(latch.await(20, TimeUnit.SECONDS)); - Assertions.assertEquals(Arrays.asList("uno", "dos", "tres"), results); - Assertions.assertEquals(Arrays.asList("one", "two", "three"), ids); - Assertions.assertEquals(Arrays.asList("eins", "zwei", "drei"), names); + org.assertj.core.api.Assertions.assertThat(results).containsExactly(null, "uno", "dos", "tres"); + org.assertj.core.api.Assertions.assertThat(ids).containsExactly(null, "one", "two", "three"); + org.assertj.core.api.Assertions.assertThat(names).containsExactly(null, "eins", "zwei", "drei"); + org.assertj.core.api.Assertions.assertThat(comments).containsExactly("dummy", null, null, null); Assertions.assertEquals(0, errors.size()); } } diff --git a/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/SseParser.java b/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/SseParser.java index e503570b362743..47b8e54957a699 100644 --- a/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/SseParser.java +++ b/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/SseParser.java @@ -145,7 +145,7 @@ private void parseEvent() { private void dispatchEvent() { // ignore empty events - if (dataBuffer.length() == 0) + if (dataBuffer.length() == 0 && commentBuffer.length() == 0) return; WebTargetImpl webTarget = sseEventSource.getWebTarget(); InboundSseEventImpl event; @@ -159,7 +159,7 @@ private void dispatchEvent() { event.setComment(commentBuffer.length() == 0 ? null : commentBuffer.toString()); // SSE spec says empty string is the default, but JAX-RS says null if not specified event.setId(lastEventId); - event.setData(dataBuffer.toString()); + event.setData(dataBuffer.length() == 0 ? null : dataBuffer.toString()); // SSE spec says "message" is the default, but JAX-RS says null if not specified event.setName(eventType); event.setReconnectDelay(eventReconnectTime); diff --git a/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/core/SseUtil.java b/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/core/SseUtil.java index b0969d595fc1ba..24de690d468c94 100644 --- a/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/core/SseUtil.java +++ b/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/core/SseUtil.java @@ -69,8 +69,10 @@ private static String serialiseEvent(ResteasyReactiveRequestContext context, Out if (event.getReconnectDelay() >= 0) serialiseField(context, sb, "retry", Long.toString(event.getReconnectDelay()), false); } - String data = serialiseDataToString(context, event, eventMediaType); - serialiseField(context, sb, "data", data, true); + if (event.getData() != null) { + String data = serialiseDataToString(context, event, eventMediaType); + serialiseField(context, sb, "data", data, true); + } sb.append(NL); // return a UTF8 buffer return sb.toString();