【问题标题】:Unmarshalling error onFailure from http POST with spray.client使用 spray.client 从 http POST 解组错误 onFailure
【发布时间】:2025-12-03 22:40:01
【问题描述】:

就此而言,我对 spray.io 和 scala 还很陌生,所以如果我没有在这里了解有关解组的术语,我提前道歉。

我正在尝试使用管道获取 HTTP POST 响应,它预计会失败,因为我需要一个授权标头,但现在让我们忽略它。

如果我使用 chrome 扩展 Postman POST 到 url,我会得到这个响应,简单明了的 json:

{"status":"error","message":"You must identify yourself to access this resource.","url":"https://scrive.com/login"}

因此,我开始为此响应创建自己的案例类,并实现了自己的 JsonProtocol,以解组响应。

case class CreateFromTemplateResult(status: String, message: String, url: String)

object ScriveJsonProtocol extends DefaultJsonProtocol {
  implicit val createFromTemplateResponseFormat = jsonFormat3(CreateFromTemplateResult)
}

所以现在我已经准备就绪,可以运行我的管道并接收响应了。

val pipeline = sendReceive ~> unmarshal[CreateFromTemplateResult]

val response = pipeline {
   Post("https://api-testbed.scrive.com/api/v1/createfromtemplate/1")
}

response onComplete {
   case Success(CreateFromTemplateResult(status, message, url)) =>
      requestContext.complete("success")

   case Failure(error) =>
      requestContext.complete(error.getMessage)
    }

请求完成,onFailure 案例运行,但 error.getMessage 不再是 json,与前面的 Postman 示例一样。

Status: 403 Forbidden
Body: {"status":"error","message":"You must identify yourself to access this resource.","url":"https://scrive.com/login"}

所以我的问题变成了,如何将返回的错误及其正文解组到我的 CreateFromTemplateResult 案例中?或者简单地进入 json 也可以。我不知道我的 onSuccess 案例是否也能奏效,我希望他们都有相同的行为。我希望它们采用我定义的 CreateFromTemplateResult 格式。

 case class CreateFromTemplateResult(status: String, message: String, url: String)

非常感谢您抽出宝贵时间,再次为我的错误术语道歉。

【问题讨论】:

    标签: scala unmarshalling spray spray-client


    【解决方案1】:

    这种情况下的错误是UnsuccessfulResponseException(你可以从代码中看到unmarshall)。所以你可以专门匹配这种情况:

    case Failure(e) => e match {
      case ure: UnsuccessfulResponseException =>
        val response = ure.response
        if(response.status = StatusCodes.Forbidden)
          complete(response.as[CreateFromTemplateResult])
        else ...
      case _ => ...
    }
    

    或者,您可能更愿意根本不使用unmarshal(或编写自己的unmarshal),而只处理sendReceive 直接返回的HttpResponse

    【讨论】:

    • 谢谢,我试试看!我将如何编写自己的解组器并直接处理 HttpResponse?听起来很有趣。
    • 如果您查看 unmarshal 的实现,这是一个非常简单的函数,我想复制它并更改它检查状态的方式。