-
Notifications
You must be signed in to change notification settings - Fork 0
/
TApply.scala
123 lines (113 loc) · 4.88 KB
/
TApply.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package com.thoughtworks.dsl.keywords.akka.http
import akka.http.scaladsl.server._
import com.thoughtworks.dsl.Dsl
import scala.language.implicitConversions
/** This [[TApply]] keyword can be used to extract the value of [[akka.http.scaladsl.server.Directive]]s, without additional indentation levels of curly brackets.
*
* @note This [[TApply]] class can be found in the following library:
*
* <pre>
* libraryDependencies += "com.thoughtworks.dsl" %% "keywords-akka-http-tapply" % "latest.release"
* </pre>
*
* @example Ordinary Akka HTTP DSL requires additional brackets to perform any directive.
*
* For example, the following `extractParametersWithBrackets` extracts query parameters `p1` and `p2` with the help of the directive [[akka.http.scaladsl.server.Directives.parameters]].
*
* {{{
* import akka.http.scaladsl.server.Directives._
* def extractParametersWithBrackets = {
* get {
* parameters("p1", "p2") { (p1, p2) =>
* complete(s"$p1, $p2!")
* }
* }
* }
*
* Get("/?p1=Hello&p2=World") ~> extractParametersWithBrackets ~> check {
* responseAs[String] should be("Hello, World!")
* }
* }}}
*
* The brackets can be avoided with the help of this [[TApply]] keyword:
*
* {{{
* def extractParametersWithoutBrackets = {
* get {
* val (p1, p2) = !TApply(parameters("p1", "p2"))
* complete(s"$p1, $p2!")
* }
* }
*
* Get("/?p1=Hello&p2=World") ~> extractParametersWithoutBrackets ~> check {
* responseAs[String] should be("Hello, World!")
* }
* }}}
*
* @example In addition, this [[TApply]] keyword can be used together with other keywords.
*
* For example, you can use [[com.thoughtworks.dsl.keywords.Using]] to automatically manage resources.
*
* {{{
* import akka.http.scaladsl.server.Directives._
* import com.thoughtworks.dsl.keywords.Using
* import com.thoughtworks.dsl.keywords.akka.http.TApply
* import java.nio.file.Files.newDirectoryStream
* import java.nio.file.Paths
* import scala.collection.JavaConverters._
*
* def currentDirectoryRoute = pathPrefix("current-directory") {
* get {
* val glob = !TApply(parameters("glob"))
* val currentDirectory = !Using(newDirectoryStream(Paths.get(""), glob))
* path("file-names") {
* complete(currentDirectory.iterator.asScala.map(_.toString).mkString(","))
* } ~ path("number-of-files") {
* complete(currentDirectory.iterator.asScala.size.toString)
* }
* }
* }
* }}}
*
* With the help of the `Using` keyword, the `currentDirectoryRoute` will open the current directory according to the glob pattern extract from the query parameter, and automatically close the directory after the HTTP request is processed completely.
*
* {{{
* Get("/current-directory/file-names?glob=*.md") ~> currentDirectoryRoute ~> check {
* responseAs[String] should be("README.md")
* }
* Get("/current-directory/file-names?glob=*.*") ~> currentDirectoryRoute ~> check {
* responseAs[String].split(',') should (contain("secret.sbt") and contain("build.sbt") and contain("README.md"))
* }
* Get("/current-directory/number-of-files?glob=*.sbt") ~> currentDirectoryRoute ~> check {
* responseAs[String] should be("2")
* }
* }}}
*/
sealed trait TApply[L] extends Any {
def directive: Directive[L]
}
object TApply {
case class TApplyN[L](directive: Directive[L]) extends AnyVal with Dsl.Keyword[TApplyN[L], L] with TApply[L]
case class TApply1[T](directive: Directive1[T]) extends AnyVal with Dsl.Keyword[TApply1[T], T] with TApply[Tuple1[T]]
@inline
def apply[L](directive: Directive[L])(
implicit dummyImplicit: DummyImplicit = DummyImplicit.dummyImplicit): TApplyN[L] = TApplyN(directive)
@inline
def apply[L](directive: Directive1[L]): TApply1[L] = TApply1(directive)
@inline
implicit def implicitTApply1[L](directive: Directive1[L]): TApply1[L] = TApply1(directive)
@inline
implicit def tApplyNDsl[L]: Dsl[TApply[L], Route, L] = new Dsl[TApply[L], Route, L] {
def cpsApply(keyword: TApply[L], handler: L => Route): Route = {
keyword.directive.tapply(handler)
}
}
@inline
implicit def tApply1Dsl[T]: Dsl[TApply[Tuple1[T]], Route, T] = new Dsl[TApply[Tuple1[T]], Route, T] {
def cpsApply(keyword: TApply[Tuple1[T]], handler: T => Route): Route = {
keyword.directive.tapply {
case Tuple1(a) => handler(a)
}
}
}
}