使用scala处理HTTP响应的最佳实践

我有ServerA公开客户端的API方法,如下所示:

def methodExposed()= Action.async(json) { req =>

    val reqAsModel = request.body.extractOpt[ClientRequestModel]

    reqAsModel match {
      case Some(clientRequest) =>
        myApiService
          .doSomething(clientRequest.someList)
          .map(res => ???)
      case None =>
        Future.successful(BadRequest("could not extract request"))
    }
  }

所以,我有一个客户端请求的case类,如果我不能从请求体中提取它,那么我返回一个带有消息的BadRequest,否则我调用内部apiService来执行这个请求的一些操作.

doSomething执行对ServerB的API调用,可以返回3个可能的响应:

> 200状态
>我需要提取到案例类的400个身体状态
> 500状态

doSomething看起来像这样:

def doSomething(list: List[String]) = {
    wSClient.url(url).withHeaders(("Content-Type", "application/json")).post(write(list)).map { response =>
      response.status match {
        case Status.BAD_REQUEST =>
          parse(response.body).extract[ServiceBResponse]
        case Status.INTERNAL_SERVER_ERROR =>
          val ex = new RuntimeException(s"ServiceB Failed with status: ${response.status} body: ${response.body}")
          throw ex
      }
    }
  }

现在我有两个问题:

>由于200返回没有正文,400有一个正文,我不知道什么应该是doSomething的返回类型
>我应该如何在控制器中处理这个并在methodExposed中正确地将响应返回给客户端?

最佳答案 如果400是常见的预期错误,我认为类型Future [要么[Your400CaseClass,Unit]]才有意义.就methodExposed如何将结果返回给客户端而言,取决于您的业务逻辑:

>客户应该被告知的基础400件事情是什么?如果doSomething遇到400时,methodExposed应该向客户端返回500
>否则,您可以将错误传播到客户端.根据业务逻辑,您可能希望也可能不希望将案例类转换为另一种形式,并可能使用不同的http代码.

如果doSomething返回500(或更一般地,任何意外的http代码),则应该抛出异常(使用Future.failed).

(最后,我希望你没有使用500来传递’正常’错误,如验证/身份验证错误.5xx代码只应用于异常和不可恢复的错误.我知道的大多数http客户端会在5xx时立即抛出异常遇到了,这意味着用户将无法处理它)

点赞