读取 vert.x http 客户端响应正文时抛出 IllegalStateException
IllegalStateException thrown when reading the vert.x http client response body
当我尝试从 http 客户端响应对象读取正文时出现以下错误。我一直没有得到异常,所以我猜这是与 CompletableFuture 相关的线程问题。知道我做错了什么吗?我用的是vert.x 3.8.1
java.lang.IllegalStateException
at io.vertx.core.http.impl.HttpClientResponseImpl.checkEnded(HttpClientResponseImpl.java:134)
at io.vertx.core.http.impl.HttpClientResponseImpl.endHandler(HttpClientResponseImpl.java:153)
at io.vertx.core.http.impl.HttpClientResponseImpl.bodyHandler(HttpClientResponseImpl.java:193)
at com.diagnostics.Response.body(Web.kt:116)
at com.diagnostics.Response.bodyNow(Web.kt:111)
at com.diagnostics.Response.bodyNow$default(Web.kt:110)
at com.diagnostics.Main.postVerificationTest(Main.kt:73)
at com.diagnostics.Main.main(Main.kt:52)
at com.diagnostics.Main.main(Main.kt)
抛出异常的代码:
val response = client.get(requestUri = "/api/info").get(3, TimeUnit.SECONDS)
val expectedStatus = 200
assertConditionOrExit(pvtLog, response.status == expectedStatus, "response status is ${response.status} expecting $expectedStatus")
val body = response.bodyNow()
assertConditionOrExit(pvtLog, body.isNotEmpty(), "body is empty expecting a non empty value")
http 客户端响应对象是从以下代码创建的:
private fun request(
method: HttpMethod,
port: Int,
host: String,
requestUri: String
): CompletableFuture<Response> {
val future = CompletableFuture<Response>()
httpClient.request(method, port, host, requestUri)
.exceptionHandler { future.completeExceptionally(it) }
.handler { resp -> future.complete(Response(resp)) }
.end()
return future
}
尸体被取回...
fun bodyNow(timeout: Long = 10, unit: TimeUnit = SECONDS): String {
return body().get(30000, SECONDS)
}
fun body(): CompletableFuture<String> {
val future = CompletableFuture<String>()
resp.bodyHandler { buff -> future.complete(buff.toString())}
return future
}
body()
函数设置 bodyHandler
在 HttpClientRequest
处理程序在 request()
方法中被调用之后。
所以有可能,当您的主线程继续运行时,事件循环接收内容并将其丢弃。如果内容很小,请求甚至可以在设置 bodyHandler
之前结束。
这就是为什么您只是偶尔看到异常的原因。
如果以后要设置bodyHandler
,必须暂停HttpClientResponse
:
httpClient.request(method, port, host, requestUri)
.exceptionHandler { future.completeExceptionally(it) }
.handler { resp ->
resp.pause() // Pause the response
future.complete(Response(resp))
}
.end()
设置bodyHandler
后恢复:
resp.bodyHandler { buff -> future.complete(buff.toString())}
resp.resume()
当我尝试从 http 客户端响应对象读取正文时出现以下错误。我一直没有得到异常,所以我猜这是与 CompletableFuture 相关的线程问题。知道我做错了什么吗?我用的是vert.x 3.8.1
java.lang.IllegalStateException
at io.vertx.core.http.impl.HttpClientResponseImpl.checkEnded(HttpClientResponseImpl.java:134)
at io.vertx.core.http.impl.HttpClientResponseImpl.endHandler(HttpClientResponseImpl.java:153)
at io.vertx.core.http.impl.HttpClientResponseImpl.bodyHandler(HttpClientResponseImpl.java:193)
at com.diagnostics.Response.body(Web.kt:116)
at com.diagnostics.Response.bodyNow(Web.kt:111)
at com.diagnostics.Response.bodyNow$default(Web.kt:110)
at com.diagnostics.Main.postVerificationTest(Main.kt:73)
at com.diagnostics.Main.main(Main.kt:52)
at com.diagnostics.Main.main(Main.kt)
抛出异常的代码:
val response = client.get(requestUri = "/api/info").get(3, TimeUnit.SECONDS)
val expectedStatus = 200
assertConditionOrExit(pvtLog, response.status == expectedStatus, "response status is ${response.status} expecting $expectedStatus")
val body = response.bodyNow()
assertConditionOrExit(pvtLog, body.isNotEmpty(), "body is empty expecting a non empty value")
http 客户端响应对象是从以下代码创建的:
private fun request(
method: HttpMethod,
port: Int,
host: String,
requestUri: String
): CompletableFuture<Response> {
val future = CompletableFuture<Response>()
httpClient.request(method, port, host, requestUri)
.exceptionHandler { future.completeExceptionally(it) }
.handler { resp -> future.complete(Response(resp)) }
.end()
return future
}
尸体被取回...
fun bodyNow(timeout: Long = 10, unit: TimeUnit = SECONDS): String {
return body().get(30000, SECONDS)
}
fun body(): CompletableFuture<String> {
val future = CompletableFuture<String>()
resp.bodyHandler { buff -> future.complete(buff.toString())}
return future
}
body()
函数设置 bodyHandler
在 HttpClientRequest
处理程序在 request()
方法中被调用之后。
所以有可能,当您的主线程继续运行时,事件循环接收内容并将其丢弃。如果内容很小,请求甚至可以在设置 bodyHandler
之前结束。
这就是为什么您只是偶尔看到异常的原因。
如果以后要设置bodyHandler
,必须暂停HttpClientResponse
:
httpClient.request(method, port, host, requestUri)
.exceptionHandler { future.completeExceptionally(it) }
.handler { resp ->
resp.pause() // Pause the response
future.complete(Response(resp))
}
.end()
设置bodyHandler
后恢复:
resp.bodyHandler { buff -> future.complete(buff.toString())}
resp.resume()