当我尝试获取像这样的亚马逊身份数据时
val pipeline: HttpRequest => Future[IdentityData] = sendReceive ~> unmarshal[IdentityData]
pipeline(Get("http://169.254.169.254/latest/dynamic/instance-identity/document"))
使用适当的case类和formatter,我收到以下异常
UnsupportedContentType(预期' application / json')
因为亚马逊将其回复标记为 text / plain 内容类型。他们也不关心 Accept 标题参数。是否有一种简单的方法可以告诉spray-json在解组时忽略它?
答案 0 :(得分:5)
在挖掘邮件列表后,我写了一个有效的功能
def mapTextPlainToApplicationJson: HttpResponse => HttpResponse = {
case r@ HttpResponse(_, entity, _, _) =>
r.withEntity(entity.flatMap(amazonEntity => HttpEntity(ContentType(MediaTypes.`application/json`), amazonEntity.data)))
case x => x
}
并在管道中使用它
val pipeline: HttpRequest => Future[IdentityData] = sendReceive ~> mapTextPlainToApplicationJson ~> unmarshal[IdentityData]
pipeline(Get("http://169.254.169.254/latest/dynamic/instance-identity/document"))
很酷的事情就是在这里你可以拦截&只要您的拦截功能具有适当的签名,就可以更改任何 HttpResponse 。
答案 1 :(得分:3)
如果你想从亚马逊响应中提取一些IdentityData
(这是一个定义为jsonFormat
的案例类),这是一个有效的json,但是你可以使用text/plain
上下文类型只需提取文本数据,将其解析为json并转换为您的数据,例如:
entity.asString.parseJson.convertTo(identityDataJsonFormat)
答案 2 :(得分:1)
我想出了一个更简单/更清洁的@ yevgeniy-mordovkin解决方案。
def setContentType(mediaType: MediaType)(r: HttpResponse): HttpResponse = {
r.withEntity(HttpEntity(ContentType(mediaType), r.entity.data))
}
用法:
val pipeline: HttpRequest => Future[IdentityData] = (
sendReceive
~> setContentType(MediaTypes.`application/json`)
~> unmarshal[IdentityData]
)
pipeline(Get("http://169.254.169.254/latest/dynamic/instance-identity/document"))