Akka(31): Http:High-Level-Api,Route rejection handling
来源:互联网 发布:韩国电视直播软件 编辑:程序博客网 时间:2024/06/05 20:04
Route 是Akka-http routing DSL的核心部分,使用户能比较方便的从http-server的角度筛选http-request、进行server运算、构建回复的http-response。所谓筛选http-request主要目的是容许request进入下一内层Route,或者拒绝reject request。比如这个~符号:它连接了上下两个独立的Route。如果上面的Route拒绝了一个request,那么下面的Route就会接着尝试这个request。一般来说:当一个筛选功能的Directive如get遇到一个不符合筛选条件的request时,它会拒绝reject这个request进入下一层Route。这时用~符号链接的下一组Route会接着尝试,直到链条最后一组Route。整个过程中的这些rejection事件会被记录下来最后由某个隐式或明式的RejectionHandler实例把这组rejection转化成HttpResponse返回用户。rejection也可以直接调用requestContext.reject(...)产生。Akka-http是通过在运行Route时用Route.seal(route)的方式来确保所有rejection在最终都会得到处理:
override def seal(system: ActorSystem, materializer: Materializer): Route = {
implicit val s = system
implicit val m = materializer
RouteAdapter(scaladsl.server.Route.seal(delegate))
}
下面是Route.seal()函数定义:
/**
* "Seals" a route by wrapping it with default exception handling and rejection conversion.
*
* A sealed route has these properties:
* - The result of the route will always be a complete response, i.e. the result of the future is a
* ``Success(RouteResult.Complete(response))``, never a failed future and never a rejected route. These
* will be already be handled using the implicitly given [[RejectionHandler]] and [[ExceptionHandler]] (or
* the default handlers if none are given or can be found implicitly).
* - Consequently, no route alternatives will be tried that were combined with this route
* using the ``~`` on routes or the [[Directive.|]] operator on directives.
*/
def seal(route: Route)(implicit
routingSettings: RoutingSettings,
parserSettings: ParserSettings = null,
rejectionHandler: RejectionHandler = RejectionHandler.default,
exceptionHandler: ExceptionHandler = null): Route = {
import directives.ExecutionDirectives._
// optimized as this is the root handler for all akka-http applications
(handleExceptions(ExceptionHandler.seal(exceptionHandler)) & handleRejections(rejectionHandler.seal))
.tapply(_ ⇒ route) // execute above directives eagerly, avoiding useless laziness of Directive.addByNameNullaryApply
}
RejectionHandler.default是Akka-http提供的默认handler。我们也可以把自定义的隐式RejectionHandler实例放在可视域内就会自动被调用了。下面是一个自定义RejectionHandler例子:
RejectionHandler.newBuilder()男性生殖器红肿痒是怎么回事?
.handle { case MissingCookieRejection(cookieName) =>
complete(HttpResponse(BadRequest, entity = "No cookies, no service!!!"))
}
.handle { case AuthorizationFailedRejection =>
complete((Forbidden, "You're out of your depth!"))
}
.handle { case ValidationRejection(msg, _) =>
complete((InternalServerError, "That wasn't valid! " + msg))
}
.handleAll[MethodRejection] { methodRejections =>
val names = methodRejections.map(_.supported.name)
complete((MethodNotAllowed, s"Can't do that! Supported: ${names mkString " or "}!"))
}
.handleNotFound { complete((NotFound, "Not here!")) }
.result()
所有Rejection类型都在Rejection.scala里定义。result()函数返回Rejection类型:
def result(): RejectionHandler =
new BuiltRejectionHandler(cases.result(), notFound, isDefault)
我们也可以用mapRejetionResponse对现成handler中产生的HttpResponse进行转换:
RejectionHandler.default
.mapRejectionResponse {
case res @ HttpResponse(_, _, ent: HttpEntity.Strict, _) =>
// since all Akka default rejection responses are Strict this will handle all rejections
val message = ent.data.utf8String.replaceAll("\"", """\"""")
// we copy the response in order to keep all headers and status code, wrapping the message as hand rolled JSON
// you could the entity using your favourite marshalling library (e.g. spray json or anything else)
res.copy(entity = HttpEntity(ContentTypes.`application/json`, s"""{"rejection": "$message"}"""))
case x => x // pass through all other types of responses
}
下面是一个比较全面的RejectionHandle应用示范:
akka.actor._
import akka.http.scaladsl.Http
import akka.http.scaladsl.model._
import akka.http.scaladsl.server._
import akka.http.scaladsl.server.Directives._
import akka.stream._
import akka.stream.scaladsl._
import akka._
import StatusCodes._
import scala.concurrent._
object RejectionHandlers {
implicit val rejectionHandler =
(RejectionHandler.newBuilder()
.handle { case MissingCookieRejection(cookieName) =>
complete(HttpResponse(BadRequest, entity = "No cookies, no service!!!"))
}
.handle { case AuthorizationFailedRejection =>
complete((Forbidden, "You're out of your depth!"))
}
.handle { case ValidationRejection(msg, _) =>
complete((InternalServerError, "That wasn't valid! " + msg))
}
.handleAll[MethodRejection] { methodRejections =>阴茎短小吃药可以刺激阴茎增长吗
val names = methodRejections.map(_.supported.name)
complete((MethodNotAllowed, s"Can't do that! Supported: ${names mkString " or "}!"))
}
.handleNotFound {
extractUnmatchedPath { p =>
complete((NotFound, s"The path you requested [${p}] does not exist."))
}
}
.result())
.mapRejectionResponse {
case res @ HttpResponse(_, _, ent: HttpEntity.Strict, _) =>
// since all Akka default rejection responses are Strict this will handle all rejections
val message = ent.data.utf8String.replaceAll("\"", """\"""")
// we copy the response in order to keep all headers and status code, wrapping the message as hand rolled JSON
// you could the entity using your favourite marshalling library (e.g. spray json or anything else)
res.copy(entity = HttpEntity(ContentTypes.`application/json`, s"""{"rejection mapped response": "$message"}"""))
case x => x // pass through all other types of responses
}
}
object RejectionHandlerDemo extends App {
import RejectionHandlers._
implicit val httpSys = ActorSystem("httpSys")
implicit val httpMat = ActorMaterializer()
implicit val httpEc = httpSys.dispatcher
val (port, host) = (8011,"localhost")
val route: Flow[HttpRequest, HttpResponse, NotUsed] = pathPrefix("hello" ~ PathEnd) {
get {
complete {Future("OK")}成都哪家男科医院治疗射精障碍好?
//HttpEntity(ContentTypes.`text/html(UTF-8)`,"
hello http server
")}
}
}
val bindingFuture: Future[Http.ServerBinding] = Http().bindAndHandle(route,host,port)
println(s"Server running at $host $port. Press any key to exit ...")
scala.io.StdIn.readLine()
bindingFuture.flatMap(_.unbind())
.onComplete(_ => httpSys.terminate())
}
- Akka(31): Http:High-Level-Api,Route rejection handling
- Akka(31): Http:High-Level-Api,Route rejection handling
- Akka(31): Http:High-Level-Api,Route rejection handling
- Akka(32): Http:High-Level-Api,Route exception handling
- Akka(30): Http:High-Level-Api,Routing DSL
- Akka(30): Http:High-Level-Api,Routing DSL
- Akka(29): Http:Server-Side-Api,Low-Level-Api
- Akka(29): Http:Server-Side-Api,Low-Level-Api
- HIGH-LEVEL IOS HTTP APIS
- route,akka
- Kafka High Level API vs. Low Level API
- Kafka High Level Consumer API in Scala
- kafka0.8 high-level consumer api使用
- YTKRequest - 基于 AFNetworking 封装的一套 High Level 的 API
- kafka Consumer high-level api 之白名单
- 使用kafka consumer high-level API开发的一些问题
- High-Performance Request-Handling Programs
- Handling large/high resolution images
- IOS info.plist文件里面添加描述
- Akka(31): Http:High-Level-Api,Route rejection handling
- U-boot的环境变量值得注意的有两个:bootcmd 和bootargs
- 不要等到双十一,几何画板带回家!
- 用caffe训练并测试自己收集的数据,踩了一堆坑
- Akka(31): Http:High-Level-Api,Route rejection handling
- php实现多进程、多线程
- webview引起的libwebviewchromium.so' is 32-bit instead of 64-bit的bug
- lucene源码-lock和directory
- TOMCAT服务器重启造成图片资源自动删除
- 在MVC中使用rdlc格式的报表
- Python3之Django Web框架模型篇(一)
- 评《程序员的***》系列
- Android各大手机品牌手机跳转到权限管理界面