我有一些带有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
}
}
}
}
}
操作Read
(GET
)、Update
(PUT
)和Delete
(DELETE
)与POST类似:
- 第一步是获取uuid
- 对于
PUT
,使用entity(as[ProductData])
获取有效负载(对于GET
和DELETE
不需要) - 调用某个返回
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)
}
}
}
}
}
1条答案
按热度按时间qacovj5a1#
你就快成功了-你的密码是:
1.您不需要泛型
T
,因为您只能从UUID.fromString
返回一个UUID
path(Segment)
会给您一个Directive
。因此,您要使用flatMap
来取回Directive
(provide
会传回一个指示词)所以它就像是
而且,是否可以将处理de future的代码封装在一个自定义指令中?
onComplete
返回一个Directive
,所以你必须返回flatMap
。要返回
BadRequest
,请在akka-http文档中查找拒绝处理程序。