summaryrefslogtreecommitdiff
path: root/cask
diff options
context:
space:
mode:
authorLi Haoyi <haoyi.li@databricks.com>2019-09-14 18:34:57 +0800
committerLi Haoyi <haoyi.li@databricks.com>2019-09-14 18:36:52 +0800
commit85e982a6bf9bd82524baf53546b31d85b426fa62 (patch)
tree4504cdc4f11543dcbeec3496707b95a464b70b86 /cask
parent2c1dcc3cd33fbd2c2c921f20f67c45ce48c1e8bc (diff)
downloadcask-85e982a6bf9bd82524baf53546b31d85b426fa62.tar.gz
cask-85e982a6bf9bd82524baf53546b31d85b426fa62.tar.bz2
cask-85e982a6bf9bd82524baf53546b31d85b426fa62.zip
`InnerResponse` is now a type param instead of member, allowing better error messages through `cask.internal.Conversion`:
``` Cannot return java.io.ByteArrayInputStream as a cask.model.Response[cask.endpoints.JsonData] ```
Diffstat (limited to 'cask')
-rw-r--r--cask/src/cask/endpoints/FormEndpoint.scala4
-rw-r--r--cask/src/cask/endpoints/JsonEndpoint.scala8
-rw-r--r--cask/src/cask/endpoints/StaticEndpoints.scala7
-rw-r--r--cask/src/cask/endpoints/WebEndpoints.scala3
-rw-r--r--cask/src/cask/endpoints/WebSocketEndpoint.scala4
-rw-r--r--cask/src/cask/internal/Conversion.scala4
-rw-r--r--cask/src/cask/main/Decorators.scala10
-rw-r--r--cask/src/cask/main/Main.scala3
-rw-r--r--cask/src/cask/main/Routes.scala8
-rw-r--r--cask/src/cask/package.scala2
10 files changed, 25 insertions, 28 deletions
diff --git a/cask/src/cask/endpoints/FormEndpoint.scala b/cask/src/cask/endpoints/FormEndpoint.scala
index 436bed4..264c169 100644
--- a/cask/src/cask/endpoints/FormEndpoint.scala
+++ b/cask/src/cask/endpoints/FormEndpoint.scala
@@ -43,8 +43,8 @@ object FormReader{
def read(ctx: Request, label: String, input: Seq[FormEntry]) = input.map(_.asInstanceOf[FormFile])
}
}
-class postForm(val path: String, override val subpath: Boolean = false) extends Endpoint {
- type InnerReturned = Response.Raw
+class postForm(val path: String, override val subpath: Boolean = false)
+ extends Endpoint[Response.Raw] {
val methods = Seq("post")
type Input = Seq[FormEntry]
diff --git a/cask/src/cask/endpoints/JsonEndpoint.scala b/cask/src/cask/endpoints/JsonEndpoint.scala
index 3b3b095..2e3373f 100644
--- a/cask/src/cask/endpoints/JsonEndpoint.scala
+++ b/cask/src/cask/endpoints/JsonEndpoint.scala
@@ -39,8 +39,8 @@ object JsonData extends DataCompanion[JsonData]{
}
}
-class postJson(val path: String, override val subpath: Boolean = false) extends Endpoint{
- type InnerReturned = Response[JsonData]
+class postJson(val path: String, override val subpath: Boolean = false)
+ extends Endpoint[Response[JsonData]]{
val methods = Seq("post")
type Input = ujson.Value
type InputParser[T] = JsReader[T]
@@ -79,8 +79,8 @@ class postJson(val path: String, override val subpath: Boolean = false) extends
def wrapPathSegment(s: String): Input = ujson.Str(s)
}
-class getJson(val path: String, override val subpath: Boolean = false) extends Endpoint{
- type InnerReturned = Response[JsonData]
+class getJson(val path: String, override val subpath: Boolean = false)
+ extends Endpoint[Response[JsonData]]{
val methods = Seq("get")
type Input = Seq[String]
type InputParser[T] = QueryParamReader[T]
diff --git a/cask/src/cask/endpoints/StaticEndpoints.scala b/cask/src/cask/endpoints/StaticEndpoints.scala
index 401f845..bf99d09 100644
--- a/cask/src/cask/endpoints/StaticEndpoints.scala
+++ b/cask/src/cask/endpoints/StaticEndpoints.scala
@@ -3,8 +3,7 @@ package cask.endpoints
import cask.main.Endpoint
import cask.model.Request
-class staticFiles(val path: String) extends Endpoint{
- type InnerReturned = String
+class staticFiles(val path: String) extends Endpoint[String]{
val methods = Seq("get")
type Input = Seq[String]
type InputParser[T] = QueryParamReader[T]
@@ -22,8 +21,8 @@ class staticFiles(val path: String) extends Endpoint{
def wrapPathSegment(s: String): Input = Seq(s)
}
-class staticResources(val path: String, resourceRoot: ClassLoader = getClass.getClassLoader) extends Endpoint{
- type InnerReturned = String
+class staticResources(val path: String, resourceRoot: ClassLoader = getClass.getClassLoader)
+ extends Endpoint[String]{
val methods = Seq("get")
type Input = Seq[String]
type InputParser[T] = QueryParamReader[T]
diff --git a/cask/src/cask/endpoints/WebEndpoints.scala b/cask/src/cask/endpoints/WebEndpoints.scala
index 7cac4f5..b52b290 100644
--- a/cask/src/cask/endpoints/WebEndpoints.scala
+++ b/cask/src/cask/endpoints/WebEndpoints.scala
@@ -7,8 +7,7 @@ import cask.model.{Request, Response}
import collection.JavaConverters._
-trait WebEndpoint extends Endpoint{
- type InnerReturned = Response.Raw
+trait WebEndpoint extends Endpoint[Response.Raw]{
type Input = Seq[String]
type InputParser[T] = QueryParamReader[T]
def wrapFunction(ctx: Request,
diff --git a/cask/src/cask/endpoints/WebSocketEndpoint.scala b/cask/src/cask/endpoints/WebSocketEndpoint.scala
index 5f35832..ca2854f 100644
--- a/cask/src/cask/endpoints/WebSocketEndpoint.scala
+++ b/cask/src/cask/endpoints/WebSocketEndpoint.scala
@@ -13,8 +13,8 @@ object WebsocketResult{
implicit class Listener(val value: WebSocketConnectionCallback) extends WebsocketResult
}
-class websocket(val path: String, override val subpath: Boolean = false) extends cask.main.BaseEndpoint{
- type InnerReturned = WebsocketResult
+class websocket(val path: String, override val subpath: Boolean = false)
+ extends cask.main.BaseEndpoint[WebsocketResult]{
val methods = Seq("websocket")
type Input = Seq[String]
type InputParser[T] = QueryParamReader[T]
diff --git a/cask/src/cask/internal/Conversion.scala b/cask/src/cask/internal/Conversion.scala
index e6a5a47..8d8ee3a 100644
--- a/cask/src/cask/internal/Conversion.scala
+++ b/cask/src/cask/internal/Conversion.scala
@@ -2,8 +2,8 @@ package cask.internal
import scala.annotation.implicitNotFound
-@implicitNotFound("Cannot return ${T} as a ${V} response")
+@implicitNotFound("Cannot return ${T} as a ${V}")
class Conversion[T, V](val f: T => V)
object Conversion{
- def create[T, V](implicit f: T => V) = new Conversion(f)
+ implicit def create[T, V](implicit f: T => V) = new Conversion(f)
}
diff --git a/cask/src/cask/main/Decorators.scala b/cask/src/cask/main/Decorators.scala
index 28d44f5..e395d5b 100644
--- a/cask/src/cask/main/Decorators.scala
+++ b/cask/src/cask/main/Decorators.scala
@@ -9,7 +9,7 @@ import cask.model.{Request, Response}
* Annotates a Cask endpoint that returns a HTTP [[Response]]; similar to a
* [[Decorator]] but with additional metadata and capabilities.
*/
-trait Endpoint extends BaseEndpoint {
+trait Endpoint[InnerReturned] extends BaseEndpoint[InnerReturned] {
type OuterReturned = Router.Result[Response.Raw]
}
@@ -17,7 +17,7 @@ trait Endpoint extends BaseEndpoint {
* An [[Endpoint]] that may return something else than a HTTP response, e.g.
* a websocket endpoint which may instead return a websocket event handler
*/
-trait BaseEndpoint extends BaseDecorator{
+trait BaseEndpoint[InnerReturned] extends BaseDecorator[InnerReturned]{
/**
* What is the path that this particular endpoint matches?
*/
@@ -55,10 +55,9 @@ trait BaseEndpoint extends BaseDecorator{
/**
* A [[Decorator]] that may deal with values other than HTTP [[Response]]s
*/
-trait BaseDecorator{
+trait BaseDecorator[InnerReturned]{
type Input
type InputParser[T] <: ArgReader[Input, T, Request]
- type InnerReturned
type Delegate = Map[String, Input] => Router.Result[InnerReturned]
type OuterReturned <: Router.Result[Any]
def wrapFunction(ctx: Request, delegate: Delegate): OuterReturned
@@ -76,10 +75,9 @@ trait BaseDecorator{
* to `wrapFunction`, which takes a `Map` representing any additional argument
* lists (if any).
*/
-trait Decorator extends BaseDecorator{
+trait Decorator extends BaseDecorator[Response.Raw]{
type OuterReturned = Router.Result[Response.Raw]
type Input = Any
- type InnerReturned = Response.Raw
type InputParser[T] = NoOpParser[Input, T]
}
diff --git a/cask/src/cask/main/Main.scala b/cask/src/cask/main/Main.scala
index 7128006..c3a4ace 100644
--- a/cask/src/cask/main/Main.scala
+++ b/cask/src/cask/main/Main.scala
@@ -94,7 +94,8 @@ abstract class BaseMain{
case head :: rest =>
head.wrapFunction(
ctx,
- args => rec(rest, args :: bindings).asInstanceOf[Router.Result[head.InnerReturned]]
+ args => rec(rest, args :: bindings)
+ .asInstanceOf[cask.internal.Router.Result[cask.model.Response.Raw]]
)
case Nil =>
diff --git a/cask/src/cask/main/Routes.scala b/cask/src/cask/main/Routes.scala
index a4660a9..5b02542 100644
--- a/cask/src/cask/main/Routes.scala
+++ b/cask/src/cask/main/Routes.scala
@@ -8,7 +8,7 @@ import language.experimental.macros
object Routes{
case class EndpointMetadata[T](decorators: Seq[Decorator],
- endpoint: BaseEndpoint,
+ endpoint: BaseEndpoint[_],
entryPoint: EntryPoint[T, _])
case class RoutesEndpointsMetadata[T](value: EndpointMetadata[T]*)
object RoutesEndpointsMetadata{
@@ -19,15 +19,15 @@ object Routes{
val routeParts = for{
m <- c.weakTypeOf[T].members
- val annotations = m.annotations.filter(_.tree.tpe <:< c.weakTypeOf[BaseDecorator]).reverse
+ val annotations = m.annotations.filter(_.tree.tpe <:< c.weakTypeOf[BaseDecorator[_]]).reverse
if annotations.nonEmpty
} yield {
- if(!(annotations.head.tree.tpe <:< weakTypeOf[BaseEndpoint])) c.abort(
+ if(!(annotations.head.tree.tpe <:< weakTypeOf[BaseEndpoint[_]])) c.abort(
annotations.head.tree.pos,
s"Last annotation applied to a function must be an instance of Endpoint, " +
s"not ${annotations.head.tree.tpe}"
)
- val allEndpoints = annotations.filter(_.tree.tpe <:< weakTypeOf[BaseEndpoint])
+ val allEndpoints = annotations.filter(_.tree.tpe <:< weakTypeOf[BaseEndpoint[_]])
if(allEndpoints.length > 1) c.abort(
annotations.head.tree.pos,
s"You can only apply one Endpoint annotation to a function, not " +
diff --git a/cask/src/cask/package.scala b/cask/src/cask/package.scala
index 51aaaf6..c3909ec 100644
--- a/cask/src/cask/package.scala
+++ b/cask/src/cask/package.scala
@@ -38,6 +38,6 @@ package object cask {
val Routes = main.Routes
type Main = main.Main
type Decorator = main.Decorator
- type Endpoint = main.Endpoint
+ type Endpoint[InnerReturned] = main.Endpoint[InnerReturned]
}