4

当我尝试获取这样的亚马逊身份数据时

val pipeline: HttpRequest => Future[IdentityData] = sendReceive ~> unmarshal[IdentityData]
pipeline(Get("http://169.254.169.254/latest/dynamic/instance-identity/document"))

使用适当的案例类和格式化程序,我收到以下异常

不支持的内容类型(预期的“应用程序/json”)

因为亚马逊将他们的回复标记为文本/纯内容类型。他们也不关心Accept标头参数。有没有一种简单的方法可以告诉 spray-json 在解组时忽略这一点?

4

3 回答 3

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 。

于 2014-06-30T13:47:59.197 回答
3

如果您想从亚马逊响应中提取一些IdentityData(这是一个带有定义的案例类),这是一个有效的 json,但使用上下文类型,您可以简单地提取文本数据,将其解析为 json 并转换为您的数据,例如:jsonFormattext/plain

entity.asString.parseJson.convertTo(identityDataJsonFormat)
于 2014-06-30T14:13:22.180 回答
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"))
于 2014-07-15T17:12:21.007 回答