Skip to content

Commit eb0b616

Browse files
authored
Merge pull request #50281 from geoand/#50252
Make compression work in Quarkus REST for streaming responses
2 parents 8f53e63 + 1ce952a commit eb0b616

File tree

2 files changed

+58
-1
lines changed

2 files changed

+58
-1
lines changed

extensions/resteasy-reactive/rest/deployment/src/main/java/io/quarkus/resteasy/reactive/server/deployment/CompressionScanner.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,24 @@ public List<HandlerChainCustomizer> scan(MethodInfo method, ClassInfo actualEndp
6666
} else {
6767
handler.setProduces(null);
6868
}
69-
return List.of(new FixedHandlerChainCustomizer(handler, HandlerChainCustomizer.Phase.AFTER_RESPONSE_CREATED));
69+
70+
// for streaming, we need to have the handler apply earlier, because streaming short-circuits the rests of the handlers
71+
return List.of(
72+
new FixedHandlerChainCustomizer(handler, isStream(produces) ? HandlerChainCustomizer.Phase.BEFORE_METHOD_INVOKE
73+
: HandlerChainCustomizer.Phase.AFTER_RESPONSE_CREATED));
74+
}
75+
76+
private static boolean isStream(String[] produces) {
77+
boolean isStream = false;
78+
if (produces != null) {
79+
for (String produce : produces) {
80+
if (produce.startsWith("text/event-stream")) {
81+
isStream = true;
82+
break;
83+
}
84+
}
85+
}
86+
return isStream;
7087
}
7188

7289
}

extensions/resteasy-reactive/rest/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/compress/CompressionTest.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
package io.quarkus.resteasy.reactive.server.test.compress;
22

33
import static io.restassured.RestAssured.get;
4+
import static org.hamcrest.core.IsNull.nullValue;
45
import static org.junit.jupiter.api.Assertions.assertEquals;
56
import static org.junit.jupiter.api.Assertions.assertTrue;
67

78
import jakarta.ws.rs.GET;
89
import jakarta.ws.rs.Path;
910
import jakarta.ws.rs.Produces;
11+
import jakarta.ws.rs.core.MediaType;
12+
import jakarta.ws.rs.sse.Sse;
13+
import jakarta.ws.rs.sse.SseEventSink;
1014

1115
import org.hamcrest.CoreMatchers;
1216
import org.jboss.resteasy.reactive.RestResponse;
@@ -52,6 +56,19 @@ public void noContent() {
5256
assertNoContent("/endpoint/void-no-content");
5357
}
5458

59+
@Test
60+
public void testStream() {
61+
get("/endpoint/stream-uncompressed")
62+
.then()
63+
.statusCode(200)
64+
.header("Content-Encoding", nullValue());
65+
66+
get("/endpoint/stream-compressed")
67+
.then()
68+
.statusCode(200)
69+
.header("Content-Encoding", "gzip");
70+
}
71+
5572
private void assertCompressed(String path) {
5673
String bodyStr = get(path).then().statusCode(200).header("Content-Encoding", "gzip").extract().asString();
5774
assertEquals(MyEndpoint.MESSAGE, bodyStr);
@@ -147,6 +164,29 @@ public RestResponse<Void> noContent() {
147164
public void voidNoContent() {
148165

149166
}
167+
168+
@GET
169+
@Produces(MediaType.SERVER_SENT_EVENTS)
170+
@Path("stream-uncompressed")
171+
public void uncompressedSseSink(Sse sse, SseEventSink sink) {
172+
doSend(sse, sink);
173+
}
174+
175+
@GET
176+
@Produces(MediaType.SERVER_SENT_EVENTS)
177+
@Compressed
178+
@Path("stream-compressed")
179+
public void compressedSseSink(Sse sse, SseEventSink sink) {
180+
doSend(sse, sink);
181+
}
182+
183+
private void doSend(Sse sse, SseEventSink sink) {
184+
for (var i = 0; i < 1000; i++) {
185+
var event = sse.newEventBuilder().data(String.class, MESSAGE).build();
186+
sink.send(event);
187+
}
188+
sink.close();
189+
}
150190
}
151191

152192
}

0 commit comments

Comments
 (0)