将错误消息从 SSE (Webflux) Spring 引导应用程序传递到 Angular 7 前端
Passing error messages from SSE (Webflux) Spring Boot app to Angular 7 frontend
我的应用程序是一个具有多个端点的 Spring 引导应用程序。我们正在尝试使用 Webflux 添加支持 SSE 的端点。
用例:
第 1 步:前端向 POST 端点提交请求并获取唯一 ID。
第 2 步:前端使用 GET 端点(启用 SSE - Flux)获取处理后的结果
Angular 使用 EventSource 对象来使用 SSE 端点。它要求终点产生text/event-stream。它对于正面测试用例非常有效。但是当服务抛出运行时异常时,Angular 前端无法获取 HTTP 状态代码和异常详细信息。它只是没有数据的错误。
抛出的异常:
@ResponseStatus(code = HttpStatus.NOT_FOUND)
public class RequestNotFoundException extends RuntimeException {
private static final long serialVersionUID = 1L;
public RequestNotFoundException(String message) {
super(message);
}
}
如 中所述,返回 Flux<ServerSentEvent>
并使用自定义事件终止通量:
Java端点
@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()));
}
这有助于通过断开连接来关闭 UI 端的连接。但我的主要问题仍然悬而未决。我应该如何将错误消息传播回前端?所有其他(正常)端点都使用上面给出的正确 HTTP 代码抛出自定义运行时异常。
我是否应该更改我的 ProcessedResult class 以获取异常详细信息?
服务器端事件使用开放的 HTTP 连接从服务器流式传输内容。根据 Eventsource HTTP 200 OK 规范 Content-Type header 需要建立连接,HTTP 500, 502, 503, 504
或任何其他网络错误将导致浏览器重新建立连接。如果满足上述情况中的 none,则会触发错误事件 readyState = 'CLOSED'
。简而言之,onError
回调仅用于处理网络超时或访问控制问题。
无法根据运行时异常发送不同的 HTTP 状态代码,因为您在建立连接时已经发送了 200 Ok。处理运行时错误的唯一方法是捕获异常并从服务器发送自定义命名事件,然后 close
EvetSource
基于该事件。
我的应用程序是一个具有多个端点的 Spring 引导应用程序。我们正在尝试使用 Webflux 添加支持 SSE 的端点。
用例:
第 1 步:前端向 POST 端点提交请求并获取唯一 ID。
第 2 步:前端使用 GET 端点(启用 SSE - Flux)获取处理后的结果
Angular 使用 EventSource 对象来使用 SSE 端点。它要求终点产生text/event-stream。它对于正面测试用例非常有效。但是当服务抛出运行时异常时,Angular 前端无法获取 HTTP 状态代码和异常详细信息。它只是没有数据的错误。
抛出的异常:
@ResponseStatus(code = HttpStatus.NOT_FOUND)
public class RequestNotFoundException extends RuntimeException {
private static final long serialVersionUID = 1L;
public RequestNotFoundException(String message) {
super(message);
}
}
如 Flux<ServerSentEvent>
并使用自定义事件终止通量:
Java端点
@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()));
}
这有助于通过断开连接来关闭 UI 端的连接。但我的主要问题仍然悬而未决。我应该如何将错误消息传播回前端?所有其他(正常)端点都使用上面给出的正确 HTTP 代码抛出自定义运行时异常。
我是否应该更改我的 ProcessedResult class 以获取异常详细信息?
服务器端事件使用开放的 HTTP 连接从服务器流式传输内容。根据 Eventsource HTTP 200 OK 规范 Content-Type header 需要建立连接,HTTP 500, 502, 503, 504
或任何其他网络错误将导致浏览器重新建立连接。如果满足上述情况中的 none,则会触发错误事件 readyState = 'CLOSED'
。简而言之,onError
回调仅用于处理网络超时或访问控制问题。
无法根据运行时异常发送不同的 HTTP 状态代码,因为您在建立连接时已经发送了 200 Ok。处理运行时错误的唯一方法是捕获异常并从服务器发送自定义命名事件,然后 close
EvetSource
基于该事件。