首页 > 解决方案 > Passing error messages from SSE (Webflux) Spring Boot app to Angular 7 frontend

问题描述

My application is a Spring Boot app with several end points. We are trying to add an SSE enabled endpoint, using Webflux.

Use case :

Step 1: Front-end submits a request to a POST endpoint and gets a unique ID.

Step 2: Front end fetches processed result using a GET endpoint (SSE enabled - Flux)

Angular uses EventSource object to consume the SSE endpoint. It requires the end point to produce text/event-stream. It works very well for positive test cases. But when runtime exceptions are thrown from the service, Angular frontend cannot get the HTTP status codes and exception details. It just errors with no data.

Thrown exceptions:

@ResponseStatus(code = HttpStatus.NOT_FOUND)
public class RequestNotFoundException extends RuntimeException {

    private static final long serialVersionUID = 1L;

    public RequestNotFoundException(String message) {
        super(message);
    }
}

As mentioned in this, returning a Flux<ServerSentEvent> and terminating the flux with a custom event:

Java endpoint

 @GetMapping(path= "{id}/async", produces=MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<ServerSentEvent<Optional<ProcessedResult>>> getProcessedResultStream(
        @PathVariable("id") @ApiParam(value = "The unique identifier of the request", required = true) String id)
        throws InterruptedException {
    // Combining data and adding a disconnect event to handle at the frontend.
    return Flux.concat(
            Flux.just(ServerSentEvent.<Optional<ProcessedResult>>builder(service.getProcessedResult(id))
                    .build()),
            Flux.just(ServerSentEvent.<Optional<ProcessedResult>>builder().event("disconnect").build()));
}

This helps to close the connection at the UI end by disconnecting it. But my main issue remains open. How should I go about propagating error messages back to the frontend ? All other (normal) endpoints throw custom runtime exceptions with proper HTTP codes as given above.

Should I change my ProcessedResult class to take exception details also ?

标签: javaangularspring-bootspring-webfluxserver-sent-events

解决方案


服务器端事件使用开放的 HTTP 连接从服务器流式传输内容。根据Eventsource的 W3C 规范, HTTP 200 OK 响应需要具有正确的 Content-Type 标头才能建立连接,HTTP 500, 502, 503, 504否则任何其他网络错误都会导致浏览器重新建立连接。如果上述情况均不满足,则使用 触发错误事件readyState = 'CLOSED'。简而言之,onError回调仅用于处理网络超时或访问控制问题。

由于您在建立连接时已经发送了 200 Ok,因此无法根据运行时异常发送不同的 HTTP 状态代码。处理运行时错误的唯一方法是捕获异常并从服务器发送自定义命名事件,并以此closeEvetSource基础。


推荐阅读