4

I have a spring-boot backend and wanted to create a SSE endpoint, sample:

@CrossOrigin(origins = "http://localhost:4200") // Angular Dev-Server
@GetMapping(path = "/stream-flux", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> streamFlux() {
    return Flux.interval(Duration.ofSeconds(1))
            .map(sequence -> "data: Flux - " + LocalTime.now().toString() + "\n\n")
            .doOnSubscribe(subscription -> {
                System.out.println("SSE-Stream started.");
            })
            .doOnNext(value -> {
                System.out.println("SSE-Value sent: " + value);
            })
            .doOnError(error -> {
                System.out.println("SSE-Error: " + error.getMessage());
            })
            .doOnComplete(() -> {
                System.out.println("SSE-Stream complete.");
            });                
}

Now, this example works perfect with an http-call (and the respective spring-server settings), tested with CURL.

curl -v http://localhost:8080/stream-flux

But when I wanted to switch to https (of course with the right spring-boot server settings)

tested with the following call:

curl -k -v https://localhost:<ssl-port>/stream-flux

The values from the event doesn't come at all with https. I am using a self-signed certificate.

And the CURL-answer is confusing to me:

* schannel: remote party requests renegotiation
* schannel: renegotiating SSL/TLS connection
* schannel: SSL/TLS connection renegotiated
* Request completely sent off

Any approach to tackling this issue is highly appreciated.

1 Answer 1

1

Spring Boot Logging Filter Blocks SSE (Server-Sent Events)

My Spring Boot application has a additional Filter that logs incoming REST requests and responses. It uses ContentCachingRequestWrapper and ContentCachingResponseWrapper to capture requests and response bodies.

Original Problem: Standard REST endpoints work fine, but SSE (text/event-stream) endpoints never send data to the client.

Cause: ContentCachingResponseWrapper buffers the entire response before passing it downstream. Since SSE is a continuous stream, it never completes, so the client never receives data.

Solution: Exclude SSE from logging To prevent this issue, I modified my filter to bypass SSE requests:

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    HttpServletRequest httpRequest = (HttpServletRequest) request;
    HttpServletResponse httpResponse = (HttpServletResponse) response;

    // Skip logging for SSE responses
    if (httpRequest.getContentType() == null || httpRequest.getContentType().equals(MediaType.TEXT_EVENT_STREAM_VALUE)) {
        chain.doFilter(request, response);
        return;
    }

    ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper(httpRequest);
    ContentCachingResponseWrapper wrappedResponse = new ContentCachingResponseWrapper(httpResponse);

    chain.doFilter(wrappedRequest, wrappedResponse);

    logRequestAndResponse(wrappedRequest, wrappedResponse);

    wrappedResponse.copyBodyToResponse();
}

Now, SSE responses are streamed directly without being cached, issue ist fixed.

Hope this helps someone facing the same problem! 😊

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.