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

Quarkus反向代理POST/PUT请求报错:Request has already been read

问题:Quarkus反向代理PUT/POST请求抛出"Request has already been read"异常

基于Quarkus搭建了一个反向代理,用于转发所有HTTP请求到另一API。GET请求可以正常工作,但PUT/POST请求失败,抛出如下异常:

java.lang.IllegalStateException: Request has already been read

实现代码如下:

处理请求的代码:

@Route(path = "/api/*")
public void handleProxyRequest(RoutingContext rc) {
   HttpServerRequest request = rc.request();
   this.httpProxy = customHttpProxy.getHttpProxy();
   this.httpProxy.handle(request);
}

CustomHttpProxy类代码:

@ApplicationScoped
public class CustomHttpProxy {


    private static final Logger LOGGER = LoggerFactory.getLogger(CustomHttpProxy.class);

    @ConfigProperty(name = "api.originport", defaultValue = "8080")
    private Integer TARGET_PORT;
    @ConfigProperty(name = "api.originhost", defaultValue = "localhost")
    private String TARGET_HOST;

    @Inject
    private Vertx vertx;

    public HttpProxy getHttpProxy() {

        HttpClient proxyClient = vertx.createHttpClient();
        HttpProxy proxy = HttpProxy.reverseProxy(proxyClient);
        proxy.origin(TARGET_PORT, TARGET_HOST);

        return proxy;
    }
}

解决方案

问题根源

  1. 频繁创建HttpClient和HttpProxy实例:每次请求都新建客户端和代理对象,既浪费资源,还会导致请求体处理的上下文冲突;
  2. 请求体被提前读取:直接提取HttpServerRequest并交给代理处理时,Quarkus/Vert.x可能已经提前读取了请求体,导致代理处理时提示请求已被读取。

修改步骤

1. 复用HttpClient和HttpProxy实例

修改CustomHttpProxy类,在初始化时创建一次客户端和代理,避免重复创建:

@ApplicationScoped
public class CustomHttpProxy {

    private static final Logger LOGGER = LoggerFactory.getLogger(CustomHttpProxy.class);

    @ConfigProperty(name = "api.originport", defaultValue = "8080")
    private Integer TARGET_PORT;
    @ConfigProperty(name = "api.originhost", defaultValue = "localhost")
    private String TARGET_HOST;

    @Inject
    private Vertx vertx;

    private HttpProxy proxy;

    @PostConstruct
    void init() {
        HttpClient proxyClient = vertx.createHttpClient();
        proxy = HttpProxy.reverseProxy(proxyClient);
        proxy.origin(TARGET_PORT, TARGET_HOST);
    }

    public HttpProxy getHttpProxy() {
        return proxy;
    }
}

2. 让代理直接处理RoutingContext

修改请求处理方法,直接将RoutingContext交给代理处理,而不是单独提取HttpServerRequest,这样能保证请求体的正确流转:

@Route(path = "/api/*")
public void handleProxyRequest(RoutingContext rc) {
    HttpProxy httpProxy = customHttpProxy.getHttpProxy();
    httpProxy.handle(rc);
}

验证说明

  • 复用HttpClient是Vert.x的官方最佳实践,能避免连接资源的不必要消耗;
  • 使用handle(rc)方法可以让代理完整接管请求的所有流程,包括请求体的读取和转发,从根本上解决"请求已被读取"的异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 08:43:17