亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何修復 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 關注
  • 329 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號