【发布时间】:2021-10-29 15:27:57
【问题描述】:
我有一些带有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?
而且,是否可以将处理未来的代码封装在自定义指令中?
例如,在顶部定义的路由将类似于:
private val createProduct = post {
path ("product") {
extractUUID { validUUID =>
entity(as[ProductData]) { productData =>
futureSuccess(addProduct(validUUID, productData)) { successValue =>
// code here, for example: complete(OK)
}
}
}
}
}
【问题讨论】: