Minor refactoring in ServerSentEvent
Extract re-usable method to serialize SSE fields. See gh-33975
This commit is contained in:
parent
fd8823819f
commit
c4b100ac0c
|
@ -20,6 +20,7 @@ import java.time.Duration;
|
||||||
|
|
||||||
import org.springframework.lang.Nullable;
|
import org.springframework.lang.Nullable;
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Representation for a Server-Sent Event for use with Spring's reactive Web support.
|
* Representation for a Server-Sent Event for use with Spring's reactive Web support.
|
||||||
|
@ -102,6 +103,34 @@ public final class ServerSentEvent<T> {
|
||||||
return this.data;
|
return this.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a StringBuilder with the id, event, retry, and comment fields fully
|
||||||
|
* serialized, and also appending "data:" if there is data.
|
||||||
|
* @since 6.2.1
|
||||||
|
*/
|
||||||
|
public String format() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
if (this.id != null) {
|
||||||
|
appendAttribute("id", this.id, sb);
|
||||||
|
}
|
||||||
|
if (this.event != null) {
|
||||||
|
appendAttribute("event", this.event, sb);
|
||||||
|
}
|
||||||
|
if (this.retry != null) {
|
||||||
|
appendAttribute("retry", this.retry.toMillis(), sb);
|
||||||
|
}
|
||||||
|
if (this.comment != null) {
|
||||||
|
sb.append(':').append(StringUtils.replace(this.comment, "\n", "\n:")).append('\n');
|
||||||
|
}
|
||||||
|
if (this.data != null) {
|
||||||
|
sb.append("data:");
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void appendAttribute(String fieldName, Object fieldValue, StringBuilder sb) {
|
||||||
|
sb.append(fieldName).append(':').append(fieldValue).append('\n');
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(@Nullable Object other) {
|
public boolean equals(@Nullable Object other) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2022 the original author or authors.
|
* Copyright 2002-2024 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -17,7 +17,6 @@
|
||||||
package org.springframework.http.codec;
|
package org.springframework.http.codec;
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.time.Duration;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -124,38 +123,19 @@ public class ServerSentEventHttpMessageWriter implements HttpMessageWriter<Objec
|
||||||
ServerSentEvent<?> sse = (element instanceof ServerSentEvent<?> serverSentEvent ?
|
ServerSentEvent<?> sse = (element instanceof ServerSentEvent<?> serverSentEvent ?
|
||||||
serverSentEvent : ServerSentEvent.builder().data(element).build());
|
serverSentEvent : ServerSentEvent.builder().data(element).build());
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
String sseText = sse.format();
|
||||||
String id = sse.id();
|
|
||||||
String event = sse.event();
|
|
||||||
Duration retry = sse.retry();
|
|
||||||
String comment = sse.comment();
|
|
||||||
Object data = sse.data();
|
Object data = sse.data();
|
||||||
if (id != null) {
|
|
||||||
writeField("id", id, sb);
|
|
||||||
}
|
|
||||||
if (event != null) {
|
|
||||||
writeField("event", event, sb);
|
|
||||||
}
|
|
||||||
if (retry != null) {
|
|
||||||
writeField("retry", retry.toMillis(), sb);
|
|
||||||
}
|
|
||||||
if (comment != null) {
|
|
||||||
sb.append(':').append(StringUtils.replace(comment, "\n", "\n:")).append('\n');
|
|
||||||
}
|
|
||||||
if (data != null) {
|
|
||||||
sb.append("data:");
|
|
||||||
}
|
|
||||||
|
|
||||||
Flux<DataBuffer> result;
|
Flux<DataBuffer> result;
|
||||||
if (data == null) {
|
if (data == null) {
|
||||||
result = Flux.just(encodeText(sb + "\n", mediaType, factory));
|
result = Flux.just(encodeText(sseText + "\n", mediaType, factory));
|
||||||
}
|
}
|
||||||
else if (data instanceof String text) {
|
else if (data instanceof String text) {
|
||||||
text = StringUtils.replace(text, "\n", "\ndata:");
|
text = StringUtils.replace(text, "\n", "\ndata:");
|
||||||
result = Flux.just(encodeText(sb + text + "\n\n", mediaType, factory));
|
result = Flux.just(encodeText(sseText + text + "\n\n", mediaType, factory));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
result = encodeEvent(sb, data, dataType, mediaType, factory, hints);
|
result = encodeEvent(sseText, data, dataType, mediaType, factory, hints);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result.doOnDiscard(DataBuffer.class, DataBufferUtils::release);
|
return result.doOnDiscard(DataBuffer.class, DataBufferUtils::release);
|
||||||
|
@ -163,7 +143,7 @@ public class ServerSentEventHttpMessageWriter implements HttpMessageWriter<Objec
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private <T> Flux<DataBuffer> encodeEvent(StringBuilder eventContent, T data, ResolvableType dataType,
|
private <T> Flux<DataBuffer> encodeEvent(CharSequence sseText, T data, ResolvableType dataType,
|
||||||
MediaType mediaType, DataBufferFactory factory, Map<String, Object> hints) {
|
MediaType mediaType, DataBufferFactory factory, Map<String, Object> hints) {
|
||||||
|
|
||||||
if (this.encoder == null) {
|
if (this.encoder == null) {
|
||||||
|
@ -171,7 +151,7 @@ public class ServerSentEventHttpMessageWriter implements HttpMessageWriter<Objec
|
||||||
}
|
}
|
||||||
|
|
||||||
return Flux.defer(() -> {
|
return Flux.defer(() -> {
|
||||||
DataBuffer startBuffer = encodeText(eventContent, mediaType, factory);
|
DataBuffer startBuffer = encodeText(sseText, mediaType, factory);
|
||||||
DataBuffer endBuffer = encodeText("\n\n", mediaType, factory);
|
DataBuffer endBuffer = encodeText("\n\n", mediaType, factory);
|
||||||
DataBuffer dataBuffer = ((Encoder<T>) this.encoder).encodeValue(data, factory, dataType, mediaType, hints);
|
DataBuffer dataBuffer = ((Encoder<T>) this.encoder).encodeValue(data, factory, dataType, mediaType, hints);
|
||||||
Hints.touchDataBuffer(dataBuffer, hints, logger);
|
Hints.touchDataBuffer(dataBuffer, hints, logger);
|
||||||
|
@ -179,10 +159,6 @@ public class ServerSentEventHttpMessageWriter implements HttpMessageWriter<Objec
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeField(String fieldName, Object fieldValue, StringBuilder sb) {
|
|
||||||
sb.append(fieldName).append(':').append(fieldValue).append('\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
private DataBuffer encodeText(CharSequence text, MediaType mediaType, DataBufferFactory bufferFactory) {
|
private DataBuffer encodeText(CharSequence text, MediaType mediaType, DataBufferFactory bufferFactory) {
|
||||||
Assert.notNull(mediaType.getCharset(), "Expected MediaType with charset");
|
Assert.notNull(mediaType.getCharset(), "Expected MediaType with charset");
|
||||||
byte[] bytes = text.toString().getBytes(mediaType.getCharset());
|
byte[] bytes = text.toString().getBytes(mediaType.getCharset());
|
||||||
|
|
Loading…
Reference in New Issue