Akka (+): Http:high-level-api,route rejection handling

Source: Internet
Author: User

Route is the core part of Akka-http routing DSL, which makes it easy for users to filter http-request from Http-server, perform server operations, and build replies Http-response. The main purpose of the so-called screening http-request is to allow request to enter the next inner route, or to reject reject request. For example, this ~ symbol: it connects up and down two separate route. If the route above rejects a request, the following route will then try the request. Generally speaking: When a directive of a filtering function encounters a request that does not meet the filter criteria, it rejects the reject request to enter the next layer of route. The next set of route with the ~ symbolic link is then tried until the last set of route is chained. These rejection events are recorded in the process and are eventually converted by an implicit or explicit Rejectionhandler instance to HttpResponse back to the user. Rejection can also call Requestcontext.reject (...) directly. Produce. Akka-http is to ensure that all rejection will be processed in the end by using Route.seal (route) when running the route:

  override def seal (System:actorsystem, materializer:materializer): Route = {    implicit Val s = system    implicit val m = materializer    routeadapter (Scaladsl.server.Route.seal (  Delegate))  }

Here is the route.seal () function definition:

  /** * "Seals" a route by wrapping it with default exception handling and rejection conversion. * * A sealed route has these properties: *-The result of the route would always be A complete response, i.e. the Res Ult of the Future is a * "Success (Routeresult.complete (response))", never a failed future and never a rejected rout   E. These * 'll be already is handled using the implicitly given [[Rejectionhandler]] and [[Exceptionhandler]] (or   * The default handlers if none is given or can be found implicitly).  *-Consequently, no route alternatives is tried that were combined with this route * using the "~" on routes   or the [[directive.|]] operator on directives. */def Seal (route:route) (Implicitroutingsettings: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 is the default handler provided by Akka-http. We can also put the custom implicit Rejectionhandler instance in the visual domain and it will be called automatically. Here is an example of a custom Rejectionhandler:

Rejectionhandler.newbuilder (). Handle { CaseMissingcookierejection (cookiename) =Complete (HttpResponse (badrequest, Entity="No cookies, no service!!!") }. Handle { CaseAuthorizationfailedrejection =Complete (Forbidden,"You ' re out of your depth!") }. Handle { CaseValidationrejection (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 ()

All rejection types are defined in Rejection.scala. The result () function returns the rejection type:

   def result (): Rejectionhandler =      new Builtrejectionhandler (Cases.result (), NotFound, IsDefault)

We can also use Maprejetionresponse to convert HttpResponse generated in off-the-shelf handler:

Rejectionhandler.default. maprejectionresponse { CaseRes @ HttpResponse (_, _, Ent:HttpEntity.Strict, _) = =//since all Akka default rejection responses is Strict This would handle all rejectionsVal 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"}"""))                       Casex = X//pass through all other types of responses}

Here is a more comprehensive demonstration of Rejectionhandle applications:

akka.actor._import akka.http.scaladsl.Httpimport 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._ObjectRejectionhandlers {ImplicitVal Rejectionhandler =(Rejectionhandler.newbuilder (). Handle { CaseMissingcookierejection (cookiename) =Complete (HttpResponse (badrequest, Entity="No cookies, no service!!!") }. Handle { CaseAuthorizationfailedrejection =Complete (Forbidden,"You ' re out of your depth!") }. Handle { CaseValidationrejection (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 { CaseRes @ HttpResponse (_, _, Ent:HttpEntity.Strict, _) = =//since all Akka default rejection responses is Strict This would handle all rejectionsVal 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"}"""))         Casex = X//pass through all other types of responses      }}ObjectRejectionhandlerdemo extends App {import Rejectionhandlers._ImplicitVal Httpsys = Actorsystem ("Httpsys")  ImplicitVal Httpmat =Actormaterializer ()ImplicitVal Httpec =Httpsys.dispatcher Val (port, host)= (8011,"localhost") Val route:flow[httprequest, HttpResponse, notused]= Pathprefix ("Hello"~pathend) {    Get{complete { the future ("OK")}      //httpentity (contenttypes. ' Text/html (UTF-8) ', "}} 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 (+): Http:high-level-api,route rejection handling

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.