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

我正在设置一个 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));


        });


莫回无
浏览 191回答 2
2回答

红糖糍粑

我解决了这个问题。在调用 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));        });

蝴蝶不菲

您可能最终会遇到此错误的两个原因: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();        ...    }}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java