You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Quarkus SSE接口添加X-Accel-Buffering等响应头

解决Quarkus BFF转发SSE在Kubernetes中无法到达浏览器的问题

直接在JAX-RS方法中设置响应头

最直接的方式是在方法中注入HttpServletResponse,在业务逻辑执行前添加需要的响应头:

@GET
@Path("/subscribe_to_invocations")
@Operation(
    operationId = "subscribeToInvocations",
    description = "Subscribe to the latest invocations")
@APIResponse(
    responseCode = "200",
    description = "OK",
    content =
        @Content(
            mediaType = MediaType.TEXT_PLAIN,
            schema = @Schema(implementation = String.class)))
@APIResponse(
    responseCode = "500",
    description = "Internal Server Error",
    content =
        @Content(
            mediaType = MediaType.APPLICATION_JSON,
            schema = @Schema(implementation = String.class)))
@Produces(MediaType.SERVER_SENT_EVENTS)
public void subscribeToInvocations(@Context Sse sse, @Context SseEventSink sink, @Context HttpServletResponse response) {
    // 提前设置禁用缓存的响应头
    response.setHeader("X-Accel-Buffering", "no");
    response.setHeader("Cache-Control", "no-cache");

    // 原有业务逻辑不变
    Response apiResponse = myApi.subscribeToInvocations();
    Multi<Msg> m =
        Multi.createFrom()
            .emitter(
                em -> {
                    SseRepeater repeater = new SseRepeater(sink, em);
                    repeater.processDownstream((InputStream) apiResponse.getEntity());
                });

    m.subscribe()
        .with(
            item -> {
                if (!sink.isClosed()) {
                    sink.send(sse.newEventBuilder().data(item.eventData()).build());
                }
            },
            failure -> {
                sink.close();
            },
            () -> {
                sink.close();
            });
}

全局过滤器方式(适用于多个SSE端点)

如果有多个SSE转发端点,可以创建ContainerResponseFilter统一添加响应头:

@Provider
@Priority(Priorities.HEADER_DECORATOR)
public class SseNoCacheHeaderFilter implements ContainerResponseFilter {

    @Override
    public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
        // 匹配所有SSE类型的响应或指定路径
        boolean isSseResponse = MediaType.SERVER_SENT_EVENTS.equals(responseContext.getMediaType());
        boolean isTargetPath = requestContext.getUriInfo().getPath().contains("/subscribe_to_invocations");
        
        if (isSseResponse || isTargetPath) {
            responseContext.getHeaders().add("X-Accel-Buffering", "no");
            responseContext.getHeaders().add("Cache-Control", "no-cache");
        }
    }
}

补充说明

  • @APIResponse注解中的header配置仅用于生成OpenAPI文档,不会实际添加到HTTP响应中,必须通过代码设置。
  • 若使用Nginx Ingress,后端设置X-Accel-Buffering: no会自动触发Nginx关闭代理缓冲,无需额外在Ingress配置中重复设置(双重设置可增强可靠性)。
  • 必须在发送第一个SSE事件前设置响应头,否则响应已提交后无法修改头信息。

内容的提问来源于stack exchange,提问作者Bernd H

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 00:34:50