我认为可以使用handleRejections
显式与mapResponse
. 首先,考虑这个简单的路由定义:
(get & path("foo")){
complete((StatusCodes.OK, HttpEntity(ContentTypes.`application/json`, """{"foo": "bar"}""" )))
}
如果我收到匹配的请求,我将使用 json 进行响应,我的调用者很高兴,因为他们可以将响应解析为 json。但是,如果您尝试使用 POST 请求调用此端点,您将收到如下响应:
HTTP 405 Method Not Allowed
Date: Wed, 06 Jan 2016 13:19:27 GMT
Content-Type: text/plain; charset=UTF-8
Content-Length: 47
Allow: GET
Server: akka-http/2.3.12
HTTP method not allowed, supported methods: GET
所以在这里我们得到了一个不可取的纯文本响应。我们可以通过在路由树的最顶部添加几个指令来普遍解决这个问题,如下所示:
mapResponse(wrapToJson){
handleRejections(RejectionHandler.default){
(get & path("foo")){
complete((StatusCodes.OK, HttpEntity(ContentTypes.`application/json`, """{"foo": "bar"}""" )))
}
}
}
被wrapToJson
定义为:
def wrapToJson(resp:HttpResponse):HttpResponse = {
//If we get a text/plain response entity, remap it otherwise do nothing
val newResp = resp.entity match{
case HttpEntity.Strict(ContentTypes.`text/plain(UTF-8)` , content ) =>
val jsonResp = s"""{"error": "${content.utf8String}"}"""
resp.copy(entity = HttpEntity(ContentTypes.`application/json`, jsonResp))
case other =>
resp
}
newResp
}
This is a very basic example, and you'd probable have a better way to generating the json, but this just serves to show how you can fix the plan text responses from the default rejection handler. Now, you must nest the default rejection handler under the mapResponse
explicitly because the automatic handling gets added outside the top level of whatever tree you define and thus mapResponse
would not see the rejection cases. You still get the default handling though via RejectionHandler.default
.
Hopefully this is close to what you were after.