Hi Evgeny,
you discovered one of the reasons for the magnet pattern. If you use 
`requireParam("param".as[Int]) { abc => ... }` then the `{ abc => }` block 
is mistaken as the implicit argument of `requireParam`. So, either you are 
ok with that and require users to use extra parentheses 
(`(requireParam("param".as[Int])) { abc => ... }`) or you use the magnet 
pattern at this level as well. You can read about the magnet pattern on the 
old spray blog (http://spray.io/blog/2012-12-13-the-magnet-pattern/) or 
just look into akka-http sources.

A better way to implement the feature would be just to use the existing 
implementation ;) and install a custom rejection handler that produces 
whatever output you would like. 
See 
https://doc.akka.io/docs/akka-http/10.0.10/scala/http/routing-dsl/rejections.html#customizing-rejection-handling
 
for how to do that.


Johannes


On Monday, November 13, 2017 at 9:22:19 AM UTC+1, Evgeny Veretennikov wrote:
>
> I developed custom generic directive, which will provide param of given 
> type, if it exists, or else reject with my custom exception.
>
> import akka.http.scaladsl.common.NameReceptacle
> import akka.http.scaladsl.server.Directives._
> import akka.http.scaladsl.server.directives.ParameterDirectives.
> ParamDefAux
> import akka.http.scaladsl.server.{Directive1, Route}
>     
> class MyCustomException(msg: String) extends Exception(msg)
>     
> def requireParam[T](name: NameReceptacle[T])
>                    (implicit pdef: ParamDefAux[NameReceptacle[T], 
> Directive1[T]]): Directive1[T] =
>   parameter(name).recover { _ =>
>     throw new MyCustomException(s"${name.name} is missed!")
>   }
>
> It works ok, if I want to create route, using two parameters, for example:
>
> val negSumParams: Route =
>   (requireParam("param1".as[Int]) & requireParam("param2".as[Int])) {
>     (param1, param2) =>
>       complete((-param1-param2).toString)
>   }
>
> But if I try to use exactly one parameter, this doesn't compile:
>
> val negParamCompilationFail: Route =
>   requireParam("param".as[Int]) {
>     param => // scalac complains about missing type param here
>       complete((-param).toString)
>   }
>
> If I use it with `pass` directive, it works:
>
> val negParamWithPass: Route =
>   (pass & requireParam("param".as[Int])) { // this pass usage looks hacky
>     param =>
>       complete((-param).toString)
>   }
>
> If I write `requireParam()` return type explicitly, it works too:
>
> val negParamWithExplicitType: Route =
>   (requireParam("param".as[Int]): Directive1[Int]) { // DRY violation
>     param =>
>       complete((-param).toString)
>   }
>
> Why do I need these tricks? Why can't it work just with 
> `requireParam("param".as[Int])`?
>
> Scala version 2.12.1, Akka-HTTP 10.0.10.
>

-- 
>>>>>>>>>>      Read the docs: http://akka.io/docs/
>>>>>>>>>>      Check the FAQ: 
>>>>>>>>>> http://doc.akka.io/docs/akka/current/additional/faq.html
>>>>>>>>>>      Search the archives: https://groups.google.com/group/akka-user
--- 
You received this message because you are subscribed to the Google Groups "Akka 
User List" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to akka-user+unsubscr...@googlegroups.com.
To post to this group, send email to akka-user@googlegroups.com.
Visit this group at https://groups.google.com/group/akka-user.
For more options, visit https://groups.google.com/d/optout.

Reply via email to