I am new to Server Sent Events (SSE) and am trying to get them working in my Spring Boot app. The problem I am having is that it doesn't seem like the events are getting sent until complete is called on the SseEmitter. In the following example I will get all (10) events plus the complete message after 10 seconds instead of one every second.
<button id="startevents" type="button" class="btn btn-primary">
Start Events
</button>
<script>
document.getElementById('startevents').addEventListener('click', function() {
const eventSource = new EventSource('/events');
eventSource.addEventListener('myevent', function(event) {
console.log('myevent: ', event.data);
});
eventSource.addEventListener('complete', function(event) {
console.log('complete: ', event.data);
eventSource.close();
});
eventSource.addEventListener('error', function(event) {
console.log('error: ', event);
});
});
</script>
@GetMapping( "/events" )
public SseEmitter republishEvents() {
SseEmitter sseEmitter = new SseEmitter(Long.MAX_VALUE);
sseEmitter.onCompletion(() -> {
log.info("SSE complete");
});
sseEmitter.onTimeout(() -> {
log.warn("SSE timeout");
sseEmitter.complete();
});
sseEmitter.onError((e) -> {
log.error("SSE error", e);
sseEmitter.complete();
});
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.execute(() -> {
try {
for ( int i = 0; i < 10; i++ ) {
log.debug( "Sending event " + i );
SseEmitter.SseEventBuilder event = SseEmitter.event()
.name("myevent")
.data( "Event " + i );
sseEmitter.send(event);
Thread.sleep( 1000 );
}
log.debug( "Sending complete event" );
SseEmitter.SseEventBuilder event = SseEmitter.event()
.name("complete")
.data( "complete" );
sseEmitter.send(event);
sseEmitter.complete();
} catch ( Exception e ) {
log.error( "Error sending event", e );
sseEmitter.complete();
} finally {
executor.shutdown();
}
});
return sseEmitter;
}
After recreating projects from scratch, that worked just fine, I eventually decided to fire up Wireshark just to see if the events were really getting sent out or not. That's when I remembered I had an nginx running locally to handle the certs and ports. Sure enough, it was buffering the events.
I added the following and everything now works fine:
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_buffering off;