Akka Http 中的自定义指令
Custom directive in Akka Http
我有一些 API 休息 CRUD
操作。
使用 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
不需要)
- 调用一些 returns
Future[Something]
的方法
我想做的是像这样删除样板文件:
- 获取
UUID
,对其进行验证,如果无效 returning Bad Request
- 创建一些 directive/function 来处理未来:如果有异常只是 return
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
和 return 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)
}
}
}
}
}
您快到了 - 您的密码是:
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)
}
}
}
- 您不需要通用
T
,因为您只能从 UUID.fromString
返回 UUID
path(Segment)
给你一个 Directive
。所以你想使用 flatMap
来获得 Directive
返回(provide
return 指令)
所以它会是这样的
def getUUID: Directive1[UUID] = {
path(Segment).flatMap { maybeuuid =>
Try(UUID.fromString(maybeuuid)) match {
case Success(result) => provide(result)
case Failure(error) => failWith(error)
}
}
}
And, is it possible to encapsulate in a custom directive the code that
handles de future?
对,同上。 onComplete
return 一个 Directive
所以你必须 flatMap
.
至 return BadRequest
,在 akka-http 文档中查找拒绝处理程序。
我有一些 API 休息 CRUD
操作。
使用 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
不需要) - 调用一些 returns
Future[Something]
的方法
我想做的是像这样删除样板文件:
- 获取
UUID
,对其进行验证,如果无效 returningBad Request
- 创建一些 directive/function 来处理未来:如果有异常只是 return
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
和 return 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)
}
}
}
}
}
您快到了 - 您的密码是:
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)
}
}
}
- 您不需要通用
T
,因为您只能从UUID.fromString
返回 path(Segment)
给你一个Directive
。所以你想使用flatMap
来获得Directive
返回(provide
return 指令)
UUID
所以它会是这样的
def getUUID: Directive1[UUID] = {
path(Segment).flatMap { maybeuuid =>
Try(UUID.fromString(maybeuuid)) match {
case Success(result) => provide(result)
case Failure(error) => failWith(error)
}
}
}
And, is it possible to encapsulate in a custom directive the code that handles de future?
对,同上。 onComplete
return 一个 Directive
所以你必须 flatMap
.
至 return BadRequest
,在 akka-http 文档中查找拒绝处理程序。