如何使用 ktor 客户端设置 HttpServletResponse 的主体
Posted
技术标签:
【中文标题】如何使用 ktor 客户端设置 HttpServletResponse 的主体【英文标题】:How to set body of HttpServletResponse using ktor client 【发布时间】:2019-11-10 16:59:29 【问题描述】:我有弹簧启动控制器
@PostMapping(path = ["/download"])
fun getFile(@RequestBody myObjectRq: myObjectRq, httpServletResponse: HttpServletResponse): CompletableFuture<HttpServletResponse>
return GlobalScope.async
val response = webService.getFile(myObjectRq)
response?.let
httpServletResponse.setHeader("Content-Type", response.headers.get("Content-Type"))
httpServletResponse.setHeader("Content-Disposition", response.headers.get("Content-Disposition"))
httpServletResponse.writer.write(String(response.content.toByteArray()))
httpServletResponse.writer.flush()
httpServletResponse.status = response.status.value
httpServletResponse
.asCompletableFuture()
在其中我使用服务,该服务又使用 ktor 客户端向外部服务器发送发布请求,外部服务器应该响应发送 csv 文件。 csv 文件内容取决于我在myObjectRq
中发送的值。
服务:
suspend fun getFile(myObjectRq: myObjectRq): HttpResponse
val response = ktorClient.post<HttpResponse>
accept(ContentType.Application.OctetStream)
url(externalWebServerUrl)
body = myObjectRq
contentType(ContentType.Application.Json)
log.info(String(response.content.toByteArray()))
response
响应的标题设置正确,方法中的log.info(String(response.content.toByteArray()))
也打印出接收文件的内容,但我不能将其设置为HttpServletResponse
的正文。我不断收到org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
。
我还得到了Inappropriate blocking method call
的httpServletResponse.writer
,这会破坏ktor 客户端的异步特性。
我做错了什么?我该如何解决?
【问题讨论】:
【参考方案1】:所以,我认为 SpringBoot 与您的返回类型混淆了。它试图找到一种方法将您的返回 CompletableFuture<HttpServletResponse>
序列化到 HTTP 响应的正文中,但失败了。我相信您可以通过如下更改实现来获得相同的结果:
@PostMapping(path = ["/download"])
fun getFile(@RequestBody myObjectRq: myObjectRq, httpServletResponse: HttpServletResponse): CompletableFuture<Void>
return GlobalScope.async
val response = webService.getFile(myObjectRq)
response?.let
httpServletResponse.setHeader("Content-Type", response.headers.get("Content-Type"))
httpServletResponse.setHeader("Content-Disposition", response.headers.get("Content-Disposition"))
httpServletResponse.writer.write(String(response.content.toByteArray()))
httpServletResponse.writer.flush()
httpServletResponse.status = response.status.value
null
.asCompletableFuture()
【讨论】:
我实际上尝试过使用 Unit,这还不错,因为响应中已打印出正文,但仍然存在弹簧错误。【参考方案2】:我实际上设法使用CompletableFuture<ResponseEntity<ByteArray>>
作为返回类型并以这种方式设置响应主体来解决这个问题:
ResponseEntity.ok().body(response.content.toByteArray())
这也删除了Inappropriate blocking method call
警告。
【讨论】:
以上是关于如何使用 ktor 客户端设置 HttpServletResponse 的主体的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 okhttp 引擎将 HostnameVerifier 添加到 ktor 客户端