[英]Best practices of handling HTTP response with scala
I have ServerA which exposes an API method for a client, which looks like this: 我有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"))
}
}
So, I have a case class for the client request and if I cannot extract it from the request body, then I return a BadRequest
with the message and otherwise I call an internal apiService
to perform some action with this request. 因此,我为客户端请求提供了一个案例类,如果无法从请求主体中提取该案例类,则返回带有消息的BadRequest
,否则我将调用内部apiService
对该请求执行某些操作。
doSomething
performs an API call to ServerB that can return 3 possible responses: doSomething
对ServerB执行API调用,该API可以返回3种可能的响应:
doSomething
looks like this: 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
}
}
}
Now I have two issues: 现在我有两个问题:
200
returns with no body and 400 has a body, I don't know what should be the return type of doSomething
由于200
没有实体,而400有实体,我不知道doSomething
的返回类型应该是什么 methodExposed
? 我应该如何在控制器中处理此问题,并在methodExposed
响应正确返回给客户端? I would do something like this: 我会做这样的事情:
case class ServiceBResponse(status: Int, body: Option[String] = None)
And then, doSomething
would be like: 然后, doSomething
就像:
def doSomething(list: List[String]) = {
wSClient.url(url).withHeaders(("Content-Type", "application/json")).post(write(list)).map { response =>
response.status match {
case Status.OK =>
ServiceBResponse(response.status)
case Status.BAD_REQUEST =>
ServiceBResponse(response.status, Option(response.body))
case Status.INTERNAL_SERVER_ERROR =>
val message = s"ServiceB Failed with status: ${response.status} body: ${response.body}"
ServiceBResponse(response.status, Option(message))
}
}
}
Finally, inside the controller: 最后,在控制器内部:
def methodExposed() = Action.async(json) { req =>
val reqAsModel = request.body.extractOpt[ClientRequestModel]
reqAsModel match {
case Some(clientRequest) =>
myApiService
.doSomething(clientRequest.someList)
.map(serviceBResponse => Status(serviceBResponse.status)(serviceBResponse.getOrElse("")))
case None =>
Future.successful(BadRequest("could not extract request"))
}
}
Another alternative is directly use WSResponse
: 另一种选择是直接使用WSResponse
:
def doSomething(list: List[String]) = {
wSClient
.url(url)
.withHeaders(("Content-Type", "application/json"))
.post(write(list))
}
And the controller: 和控制器:
def methodExposed() = Action.async(json) { req =>
val reqAsModel = request.body.extractOpt[ClientRequestModel]
reqAsModel match {
case Some(clientRequest) =>
myApiService
.doSomething(clientRequest.someList)
.map(wsResponse => Status(wsResponse.status)(wsResponse.body))
case None =>
Future.successful(BadRequest("could not extract request"))
}
}
If 400 is a common expected error, I think the type Future[Either[Your400CaseClass, Unit]]
makes sense. 如果400是常见的预期错误,我认为类型Future[Either[Your400CaseClass, Unit]]
是有意义的。 In terms of how methodExposed
returns the result to the client depends on your business logic: 关于methodExposed
如何将结果返回给客户端的方式取决于您的业务逻辑:
You should throw an exception (using Future.failed) if doSomething
returns 500 (or more generally, any unexpected http code). 如果doSomething
返回500(或更常见的是任何意外的http代码),则应引发异常(使用Future.failed)。
(Lastly, I hope you're not using 500 to communicate a 'normal' error like validation / authentication error. 5xx code should only be used for exceptional and unrecoverable errors. Most http clients I know will throw an exception immediately when a 5xx is encountered, which means the user won't get the chance to handle it) (最后,我希望您不要使用500来传达“正常”错误,例如验证/身份验证错误。5xx代码仅应用于例外和不可恢复的错误。我知道的大多数HTTP客户端在5xx为遇到,这意味着用户将没有机会处理它)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.