【问题标题】:Akka HighLevelHttp return Route from recovering FutureAkka HighLevelHttp 从恢复 Future 返回 Route
【发布时间】:2021-07-14 16:02:53
【问题描述】:

因为我有一个请求正文,所以我需要将它作为未来获取并在操作后发送响应。但是,我需要检查 body 是否有效,如果不是,我想返回一个 BadRequest 状态。

我知道代码太多,所以请看requestFuture里面,recover函数是问题。

(pathPrefix("api" / "search") & post & extractRequest) { request =>
  val tokenResult = request.headers.find(x => x.name.toLowerCase == "token")
    tokenResult match {
      case None => throw new IllegalArgumentException(ServerMessages.TOKEN_NOT_FOUND)
      case Some(token) => token.value match {
        case this.apiToken => {
          val entity = request.entity
          val strictEntityFuture = entity.toStrict(2 seconds)
          val requestFuture = strictEntityFuture
              .map(_.data.utf8String.parseJson
                .convertTo[SearchFilters])

          requestFuture map { filters =>
             // here - I return an Route with data from controller
             complete(controller.searchData(filters)
               .map(_.toJson.prettyPrint)
               .map(toHttpEntity)))
          } recover (e => {
             // HERE IS THE PROBLEM
             // I need to return an Route, but here will be a Future[Route]
             complete(400 -> ServerMessages.INVALID_REQUEST_BODY)
          }
        }
        case _ => throw new IllegalArgumentException(ServerMessages.INVALID_TOKEN)
      }
}

我需要解压来自未来的响应,或者使用其他方式抛出错误。

使用onComplete 指令找到了解决方案,但我需要知道我的 json 是否成功转换,才能引发自定义错误。

onComplete(requestFuture) {
    case Success(filters) => searchKpi(filters) ~
       pathEndOrSingleSlash {
           complete(403 -> ServerMessages.INVALID_METHOD_ARGUMENTS)
       }
    case Failure(ex) => failWith(ex) // returns 500 Internal Server Error
}

谢谢

【问题讨论】:

    标签: scala routes akka future akka-http


    【解决方案1】:

    您可以使用ExceptionHandler

    像在文档中一样定义您的异常处理程序,并将您的异常(应该与 failWith 抛出的相同)添加一个案例到您需要返回的 HTTP 状态(您提到 BadRequest

        case class MyBadException() extends RuntimeException
    
      implicit def myExceptionHandler: ExceptionHandler =
        ExceptionHandler {
          case MyBadException() => complete(HttpResponse(BadRequest)) // You decide the HTTP status to return
          case _ => complete(HttpResponse(InternalServerError, entity = "Bad numbers, bad result!!!"))
        }
    
    
        val route = path("test") {
          onComplete(getSomething()) {
            case Success(v) => complete("Ok")
            case Failure(err) => failWith(MyBadException())
          }
        }
    
    

    请注意,您有两种附加异常处理程序的方法

    来自文档:

    Bring it into implicit scope at the top-level.
    Supply it as argument to the handleExceptions directive.
    

    【讨论】:

      【解决方案2】:

      尝试类似:

      val requestFuture = strictEntityFuture
      
      requestFuture.map { entity =>
        entity.data.utf8String match {
        // Do your processing here
        case "" => RouteResult.Complete(HttpResponse(StatusCode.int2StatusCode(200), entity = HttpEntity("OK")))
      }}.recover {
        case err: Throwable =>
        RouteResult.Complete(HttpResponse(StatusCode.int2StatusCode(500), entity = HttpEntity(err.getMessage)))
      }
      

      【讨论】:

        【解决方案3】:

        我已经有一个Exception Handler,但只有 2 个案例(IllegalArgumentNoSuchElement)。感谢ccheneson,我将处理程序扩展为可以返回BadRequest 响应。但是我在那里做错了,因为我的BadRequestException 被打包到defaultExceptionHandler 路由。

        val routes = (
            handleExceptions(noSuchElementExceptionHandler) &
              handleExceptions(tokenNotFoundExceptionHandler)) {
            domainRoutes
          }
        
        private val domainRoutes = {
           onComplete(future) {
              case Success(values) => complete(controller.getdata(values))
              case Failure(e) => failWith(BadRequestExceptionHandler(e.getMessage))
           }
        }
        

        【讨论】:

        • 你可以做类似handleExceptions(noSuchElementExceptionHandler.withFallback(tokenNotFoundExceptionHandler).withFallback(defaultExceptionHandler))
        猜你喜欢
        • 1970-01-01
        • 2013-01-24
        • 1970-01-01
        • 1970-01-01
        • 2017-08-02
        • 1970-01-01
        • 2015-09-22
        • 2021-11-25
        • 1970-01-01
        相关资源
        最近更新 更多