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));
});
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();
...
}
}
添加回答
举报