Akka Http中的自定义指令

bkhjykvo  于 2022-11-05  发布在  其他
关注(0)|答案(1)|浏览(229)

我有一些带有CRUD操作的API Rest。每个实体都用UUID来标识。
例如,对于Create,它类似于:

private val createProduct = post {
    path("product" / Segment) { productUUID =>
        Try(UUID.fromString(productUUID)) match {
          case Failure(_) => // Bad request
          case Success(validUuid) =>
            entity(as[ProductData]) { productData =>
              onComplete(addProduct(validUuid, productData)) {
                case Success(_)  => complete(StatusCodes.OK)
                case Failure(ex) => // some code 
              }
            }
        }
    }
  }

操作ReadGET)、UpdatePUT)和DeleteDELETE)与POST类似:

  • 第一步是获取uuid
  • 对于PUT,使用entity(as[ProductData])获取有效负载(对于GETDELETE不需要)
  • 调用某个返回Future[Something]方法

我想做的是删除样板文件,如:

  • 获取UUID,验证它,如果它无效,则返回Bad Request
  • 创建一些指令/函数用于处理未来:如果出现异常,则返回500 Internal Server Error,但如果出现Success,则继续处理该值(我认为使用provide指令)。

我找到了这个例子(https://fmsbeekmans.com/blog/akka-http-2-creating-custom-directives.html):

def simplifiedOnComplete[T](future: Future[T])(timeout: FiniteDuration): Directive1[T] = {
  Try(Await.result(future, Duration.Inf)) match {
    case Success(result) => provide(result)
    case Failure(error) => failWith(error)
  }
}

我说,好吧,在这个例子中有一个尝试!也许我可以改变它,使用UUID而不是Future

def getUUID[T]: Directive1[T] = {
    path(Segment) { maybeuuid =>
      Try(UUID.fromString(maybeuuid)) match {
        case Success(result) => provide(result) // compilation error here
        case Failure(error)  => failWith(error)
      }
    }
  }

代码未编译,并出现以下错误:Type mismatch. Required: Route, found: Directive1[UUID]我想问题是我添加了path...
如何创建一个Directive来提取有效的uuid,如果它无效,则返回Bad Request?是否可以将处理de future的代码封装在一个自定义指令中?
例如,在顶部定义的路由如下所示:

private val createProduct = post {
     path ("product") {
        extractUUID { validUUID =>
           entity(as[ProductData]) { productData => 
              futureSuccess(addProduct(validUUID, productData)) { successValue =>
                 // code here, for example: complete(OK)
              }
           }
        }
     }
  }
qacovj5a

qacovj5a1#

你就快成功了-你的密码是:

def getUUID[T]: Directive1[T] = {
    path(Segment) { maybeuuid =>
      Try(UUID.fromString(maybeuuid)) match {
        case Success(result) => provide(result) // compilation error here
        case Failure(error)  => failWith(error)
      }
    }
  }

1.您不需要泛型T,因为您只能从UUID.fromString返回一个UUID

  1. path(Segment)会给您一个Directive。因此,您要使用flatMap来取回Directiveprovide会传回一个指示词)
    所以它就像是
def getUUID: Directive1[UUID] = {
    path(Segment).flatMap { maybeuuid =>
      Try(UUID.fromString(maybeuuid)) match {
        case Success(result) => provide(result) 
        case Failure(error)  => failWith(error)
      }
    }
  }

而且,是否可以将处理de future的代码封装在一个自定义指令中?
onComplete返回一个Directive,所以你必须返回flatMap
要返回BadRequest,请在akka-http文档中查找拒绝处理程序。

相关问题