Spray.io:从text / json到application / json的映射请求

时间:2014-01-26 10:18:10

标签: spray

我正在尝试用纯喷雾罐+喷涂路线替换基于Jetty的后端。

前端使用text/json媒体类型发布JSON内容。我和Jetty从来没有遇到任何问题。我刚刚意识到它不是一种标准类型,这要归功于spray,它只接受正确且标准的application/json媒体类型。

有没有简单的方法可以在服务器端将一个映射到另一个?我真的希望避免引入应用程序客户端的临时版本来处理这个问题。当然,我会为下一个预定版本进行更改,但是现在我需要一个“快速而肮脏”的修复。

我尝试使用以下函数将标题从text/json更改为application/json

def correctJsonHeaders(req:spray.http.HttpRequest) = {
  val tweakedHeaders = req.headers.map{ hdr =>
    if(hdr.name == "Content-Type" && hdr.value == "text/json")
      `Content-Type`(`application/json`)
    else
      hdr
  }
  req.copy(headers = tweakedHeaders)
}

在我的路线指令中,如下:

path("route"){
  mapRequest(correctJsonHeaders){
    post{
      respondWithMediaType(`application/json`) {
        handleWith{ x:TypeThatUnmarshallsFromJson =>
          bizLogicReturningAJsonString(x)
        }
      }
    }
  }
}

虽然标题已正确更改,但我仍然会收到415错误(如果我在客户端将媒体类型更改为application/json,则会失败)

2 个答案:

答案 0 :(得分:1)

在阅读了sp-http内容类型标题上的documentation之后,我将我的功能更改为:

def correctJsonHeaders(req:spray.http.HttpRequest) = {
  if(req.headers.exists(hdr => hdr.name == "Content-Type" && hdr.value == "text/json")){
    val tweakedEntity = spray.http.HttpEntity(`application/json`, req.entity.data)
    req.copy(entity = tweakedEntity)
  }
  else req
}

似乎有用。诀窍是改变HttpEntity,而不是标题。

答案 1 :(得分:0)

缺少对自定义Accept和Content-Type标头的支持是由您使用的JSON编组器的实现引起的。看看这些特征的源代码,看看发生了什么:

  • spray.httpx.LiftJsonSupport
  • spray.httpx.Json4sJacksonSupport
  • spray.httpx.PlayJsonSupport
  • spray.httpx ....

只需通过实现自己的PlayJsonSupport特性并将自定义MediaType和ContentType添加到两个委托函数来解决此问题。我们也需要这个,因为我们将供应商版本放在我们的接受标头中,以支持我们的REST服务的版本控制。