为了账号安全,请及时绑定邮箱和手机立即绑定

如何修复 Vert.x 中的“请求已被读取”错误

如何修复 Vert.x 中的“请求已被读取”错误

莫回无 2023-06-28 15:49:21
我正在设置一个 api 网关。我想在请求 BE 服务之前验证授权令牌。我收到 IllegalStateException: 请求已被读取。请帮忙。我将测试项目代码上传到GitHub。 router.route().path("/user/admin").method(HttpMethod.POST)        .handler(rct -> {            HttpServerRequest request = rct.request().setExpectMultipart(true);            MultiMap headers = request.headers();            JsonObject param = new JsonObject().put("requestUrl", "http://localhost:18080/authorize")                    .put("httpMethod", "POST");            webClient.postAbs("http://localhost:18080/authorize")                    .timeout(6000)                    .putHeader("Content-Type", "application/json")                    .putHeader("Authorization", headers.get("Authorization"))                    .as(BodyCodec.jsonObject())                    .sendJsonObject(param, ar -> authHandler(rct, ar));        });
查看完整描述

2 回答

?
红糖糍粑

TA贡献1815条经验 获得超6个赞

我解决了这个问题。在调用 auth api 之前,我暂停原始请求,并在授权完成后恢复缓冲区处理。


router.route().path("/user/admin").method(HttpMethod.POST)

        .handler(rct -> {


            HttpServerRequest request = rct.request().setExpectMultipart(true);


            request.pause(); // Here is to pasue the origin request.


            MultiMap headers = request.headers();


            JsonObject param = new JsonObject().put("requestUrl", "http://localhost:18080/authorize")

                    .put("httpMethod", "POST");


            webClient.postAbs("http://localhost:18080/authorize")

                    .timeout(6000)

                    .putHeader("Content-Type", "application/json")

                    .putHeader("Authorization", headers.get("Authorization"))

                    .as(BodyCodec.jsonObject())

                    .sendJsonObject(param, ar -> authHandler(rct, ar));


        });


查看完整回答
反对 回复 2023-06-28
?
蝴蝶不菲

TA贡献1810条经验 获得超4个赞

您可能最终会遇到此错误的两个原因:

A) 异步Handler之前BodyHandler

正如 Vert.X文档中所述BodyHandler

使用此处理程序需要尽快将其安装在路由器中,因为它需要安装处理程序来使用 HTTP 请求正文,并且必须在执行任何异步调用之前完成此操作。

修复1:更改顺序:

router.post(endpoint)
   .consumes(contentType)
   .handler(bodyHandler)  <<<<<<<<< first this
   .handler(authHandler) <<<<<<<<  then this async handler;

修复 2:暂停/恢复请求传送:

请参阅 Vert.X文档:

如果之前需要异步调用,则应暂停 HttpServerRequest ,然后再恢复,以便在主体处理程序准备好处理请求事件之前不会传递请求事件。

router.post(endpoint)
   .consumes(contentType)
   .handler(authHandler)
   .handler(bodyHandler);

BodyHandler implements Handler<RoutingContext> {

  @Override

  public void handle(final RoutingContext ctx) {


     // pause request delivery

     ctx.request().pause();


     asyncCall(r -> {

        // e.g. check authorization or database here


        // resume request delivery

        ctx.request.resume();


        // call the next handler

        ctx.next();

     }

  }

}

B) 多次request.body()调用

假设您使用 Vert.XBodyHandler并在其后安装了自定义处理程序:

router.post(endpoint)
   .consumes(contentType)
   .handler(BodyHandler.create())
   .handler(customHandler);

您的自定义处理程序不得调用request.body()否则你会得到

403: body has already been read

修复:使用ctx.getBody()

用于ctx.getBody[/asJson/asString]()获取已被读取的正文BodyHandler

CustomHandler implements Handler<RoutingContext> {

    @Override

    public void handleAuthorizedRequest(RoutingContext ctx) {

        final var body = ctx.getBodyAsJson();


        // instead of: ctx.request().body();

        ...

    }

}


查看完整回答
反对 回复 2023-06-28
  • 2 回答
  • 0 关注
  • 190 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信