Allow sending SSE events without data
Prior to this commit, the SseBuilder API in WebMvc.fn would only allow to send Server-Sent Events with `data:` items in them. The spec doesnn't disallow this and other specifications rely on such patterns to signal the completion of a stream, like: ``` event:next data:some data event:complete ``` This commit adds a new `send()` method without any argument that sends the buffered content (id, event comment and retry) without data. Fixes: gh-32270
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -570,6 +570,15 @@ public interface ServerResponse {
|
||||
*/
|
||||
void send(Object object) throws IOException;
|
||||
|
||||
/**
|
||||
* Sends the buffered content as a server-sent event, without data.
|
||||
* Only the {@link #event(String) events} and {@link #comment(String) comments}
|
||||
* will be sent.
|
||||
* @throws IOException in case of I/O errors
|
||||
* @since 6.1.4
|
||||
*/
|
||||
void send() throws IOException;
|
||||
|
||||
/**
|
||||
* Add an SSE "id" line.
|
||||
* @param id the event identifier
|
||||
|
||||
@@ -135,6 +135,23 @@ final class SseServerResponse extends AbstractServerResponse {
|
||||
data(object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send() throws IOException {
|
||||
this.builder.append('\n');
|
||||
try {
|
||||
OutputStream body = this.outputMessage.getBody();
|
||||
body.write(builderBytes());
|
||||
body.flush();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
this.sendFailed = true;
|
||||
throw ex;
|
||||
}
|
||||
finally {
|
||||
this.builder.setLength(0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SseBuilder id(String id) {
|
||||
Assert.hasLength(id, "Id must not be empty");
|
||||
@@ -186,20 +203,7 @@ final class SseServerResponse extends AbstractServerResponse {
|
||||
for (String line : lines) {
|
||||
field("data", line);
|
||||
}
|
||||
this.builder.append('\n');
|
||||
|
||||
try {
|
||||
OutputStream body = this.outputMessage.getBody();
|
||||
body.write(builderBytes());
|
||||
body.flush();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
this.sendFailed = true;
|
||||
throw ex;
|
||||
}
|
||||
finally {
|
||||
this.builder.setLength(0);
|
||||
}
|
||||
this.send();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -32,8 +32,10 @@ import org.springframework.web.testfixture.servlet.MockHttpServletResponse;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link ServerResponse.SseBuilder}.
|
||||
* @author Arjen Poutsma
|
||||
* @author Sebastien Deleuze
|
||||
* @author Brian Clozel
|
||||
*/
|
||||
class SseServerResponseTests {
|
||||
|
||||
@@ -151,6 +153,26 @@ class SseServerResponseTests {
|
||||
assertThat(this.mockResponse.getContentAsString()).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
void sendWithoutData() throws Exception {
|
||||
ServerResponse response = ServerResponse.sse(sse -> {
|
||||
try {
|
||||
sse.event("custom").send();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new UncheckedIOException(ex);
|
||||
}
|
||||
});
|
||||
|
||||
ServerResponse.Context context = Collections::emptyList;
|
||||
|
||||
ModelAndView mav = response.writeTo(this.mockRequest, this.mockResponse, context);
|
||||
assertThat(mav).isNull();
|
||||
|
||||
String expected = "event:custom\n\n";
|
||||
assertThat(this.mockResponse.getContentAsString()).isEqualTo(expected);
|
||||
}
|
||||
|
||||
|
||||
private static final class Person {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user