diff options
author | Li Haoyi <haoyi.li@databricks.com> | 2019-09-14 16:45:39 +0800 |
---|---|---|
committer | Li Haoyi <haoyi.li@databricks.com> | 2019-09-14 17:40:26 +0800 |
commit | 4e853a9d5b9563dbe1909757bf4be4d8e7d2b36a (patch) | |
tree | 684863947658d22f91804090c81a68d012b82b6c /cask/src/cask/endpoints | |
parent | 90b6806e5fb91b207f9d8e2da2a58c25928badea (diff) | |
download | cask-4e853a9d5b9563dbe1909757bf4be4d8e7d2b36a.tar.gz cask-4e853a9d5b9563dbe1909757bf4be4d8e7d2b36a.tar.bz2 cask-4e853a9d5b9563dbe1909757bf4be4d8e7d2b36a.zip |
.
Diffstat (limited to 'cask/src/cask/endpoints')
-rw-r--r-- | cask/src/cask/endpoints/FormEndpoint.scala | 7 | ||||
-rw-r--r-- | cask/src/cask/endpoints/JsonEndpoint.scala | 55 | ||||
-rw-r--r-- | cask/src/cask/endpoints/StaticEndpoints.scala | 8 | ||||
-rw-r--r-- | cask/src/cask/endpoints/WebEndpoints.scala | 14 | ||||
-rw-r--r-- | cask/src/cask/endpoints/WebSocketEndpoint.scala | 17 |
5 files changed, 71 insertions, 30 deletions
diff --git a/cask/src/cask/endpoints/FormEndpoint.scala b/cask/src/cask/endpoints/FormEndpoint.scala index 471c5e5..436bed4 100644 --- a/cask/src/cask/endpoints/FormEndpoint.scala +++ b/cask/src/cask/endpoints/FormEndpoint.scala @@ -44,13 +44,13 @@ object FormReader{ } } class postForm(val path: String, override val subpath: Boolean = false) extends Endpoint { - type Output = Response + type InnerReturned = Response.Raw val methods = Seq("post") type Input = Seq[FormEntry] type InputParser[T] = FormReader[T] def wrapFunction(ctx: Request, - delegate: Map[String, Input] => Router.Result[Output]): Router.Result[Response] = { + delegate: Delegate): Router.Result[Response.Raw] = { try { val formData = FormParserFactory.builder().build().createParser(ctx.exchange).parseBlocking() delegate( @@ -62,7 +62,8 @@ class postForm(val path: String, override val subpath: Boolean = false) extends ) } catch{case e: Exception => Router.Result.Success(cask.model.Response( - "Unable to parse form data: " + e + "\n" + Util.stackTraceString(e) + "Unable to parse form data: " + e + "\n" + Util.stackTraceString(e), + statusCode = 400 )) } } diff --git a/cask/src/cask/endpoints/JsonEndpoint.scala b/cask/src/cask/endpoints/JsonEndpoint.scala index e0d1257..edf0c46 100644 --- a/cask/src/cask/endpoints/JsonEndpoint.scala +++ b/cask/src/cask/endpoints/JsonEndpoint.scala @@ -1,11 +1,11 @@ package cask.endpoints -import java.io.ByteArrayOutputStream +import java.io.{ByteArrayOutputStream, InputStream, OutputStream, OutputStreamWriter} import cask.internal.{Router, Util} import cask.main.Endpoint import cask.model.{Request, Response} - +import collection.JavaConverters._ sealed trait JsReader[T] extends Router.ArgReader[ujson.Value, T, cask.model.Request] object JsReader{ @@ -26,13 +26,25 @@ object JsReader{ } } } +trait JsonData extends Response.Data +object JsonData{ + implicit class JsonDataImpl[T: upickle.default.Writer](t: T) extends JsonData{ + def write(out: OutputStream) = { + val writer = new OutputStreamWriter(out) + implicitly[upickle.default.Writer[T]].write(new ujson.BaseRenderer(writer), t) + writer.flush() + } + } +} + class postJson(val path: String, override val subpath: Boolean = false) extends Endpoint{ - type Output = Response + type InnerReturned = Response[JsonData] val methods = Seq("post") - type Input = ujson.Js.Value + type Input = ujson.Value type InputParser[T] = JsReader[T] + override type OuterReturned = Router.Result[Response.Raw] def wrapFunction(ctx: Request, - delegate: Map[String, Input] => Router.Result[Output]): Router.Result[Response] = { + delegate: Delegate): Router.Result[Response.Raw] = { val obj = for{ str <- try { @@ -41,21 +53,42 @@ class postJson(val path: String, override val subpath: Boolean = false) extends Right(new String(boas.toByteArray)) } catch{case e: Throwable => Left(cask.model.Response( - "Unable to deserialize input JSON text: " + e + "\n" + Util.stackTraceString(e) + "Unable to deserialize input JSON text: " + e + "\n" + Util.stackTraceString(e), + statusCode = 400 ))} json <- try Right(ujson.read(str)) catch{case e: Throwable => Left(cask.model.Response( - "Input text is invalid JSON: " + e + "\n" + Util.stackTraceString(e) + "Input text is invalid JSON: " + e + "\n" + Util.stackTraceString(e), + statusCode = 400 ))} obj <- try Right(json.obj) - catch {case e: Throwable => Left(cask.model.Response("Input JSON must be a dictionary"))} + catch {case e: Throwable => Left(cask.model.Response( + "Input JSON must be a dictionary", + statusCode = 400 + ))} } yield obj.toMap obj match{ - case Left(r) => Router.Result.Success(r) - case Right(params) => delegate(params) + case Left(r) => Router.Result.Success(r.map(Response.Data.StringData)) + case Right(params) => delegate(params).map(_.data) } } - def wrapPathSegment(s: String): Input = ujson.Js.Str(s) + def wrapPathSegment(s: String): Input = ujson.Str(s) } + +class getJson(val path: String, override val subpath: Boolean = false) extends Endpoint{ + type InnerReturned = Response[JsonData] + val methods = Seq("get") + type Input = Seq[String] + type InputParser[T] = QueryParamReader[T] + override type OuterReturned = Router.Result[Response.Raw] + def wrapFunction(ctx: Request, + delegate: Delegate): Router.Result[Response.Raw] = { + + val res = delegate(WebEndpoint.buildMapFromQueryParams(ctx)) + + res.map(_.data) + } + def wrapPathSegment(s: String) = Seq(s) +}
\ No newline at end of file diff --git a/cask/src/cask/endpoints/StaticEndpoints.scala b/cask/src/cask/endpoints/StaticEndpoints.scala index fd194ca..401f845 100644 --- a/cask/src/cask/endpoints/StaticEndpoints.scala +++ b/cask/src/cask/endpoints/StaticEndpoints.scala @@ -4,12 +4,12 @@ import cask.main.Endpoint import cask.model.Request class staticFiles(val path: String) extends Endpoint{ - type Output = String + type InnerReturned = String val methods = Seq("get") type Input = Seq[String] type InputParser[T] = QueryParamReader[T] override def subpath = true - def wrapFunction(ctx: Request, delegate: Delegate): Returned = { + def wrapFunction(ctx: Request, delegate: Delegate): OuterReturned = { delegate(Map()).map(t => cask.model.StaticFile( (cask.internal.Util.splitPath(t) ++ ctx.remainingPathSegments) @@ -23,12 +23,12 @@ class staticFiles(val path: String) extends Endpoint{ } class staticResources(val path: String, resourceRoot: ClassLoader = getClass.getClassLoader) extends Endpoint{ - type Output = String + type InnerReturned = String val methods = Seq("get") type Input = Seq[String] type InputParser[T] = QueryParamReader[T] override def subpath = true - def wrapFunction(ctx: Request, delegate: Delegate): Returned = { + def wrapFunction(ctx: Request, delegate: Delegate): OuterReturned = { delegate(Map()).map(t => cask.model.StaticResource( (cask.internal.Util.splitPath(t) ++ ctx.remainingPathSegments) diff --git a/cask/src/cask/endpoints/WebEndpoints.scala b/cask/src/cask/endpoints/WebEndpoints.scala index ab3b480..7cac4f5 100644 --- a/cask/src/cask/endpoints/WebEndpoints.scala +++ b/cask/src/cask/endpoints/WebEndpoints.scala @@ -8,12 +8,17 @@ import collection.JavaConverters._ trait WebEndpoint extends Endpoint{ - type Output = Response + type InnerReturned = Response.Raw type Input = Seq[String] type InputParser[T] = QueryParamReader[T] def wrapFunction(ctx: Request, - delegate: Map[String, Input] => Router.Result[Output]): Router.Result[Response] = { - + delegate: Delegate): Router.Result[Response.Raw] = { + delegate(WebEndpoint.buildMapFromQueryParams(ctx)) + } + def wrapPathSegment(s: String) = Seq(s) +} +object WebEndpoint{ + def buildMapFromQueryParams(ctx: Request) = { val b = Map.newBuilder[String, Seq[String]] val queryParams = ctx.exchange.getQueryParameters for(k <- queryParams.keySet().iterator().asScala){ @@ -22,9 +27,8 @@ trait WebEndpoint extends Endpoint{ deque.toArray(arr) b += (k -> (arr: Seq[String])) } - delegate(b.result()) + b.result() } - def wrapPathSegment(s: String) = Seq(s) } class get(val path: String, override val subpath: Boolean = false) extends WebEndpoint{ val methods = Seq("get") diff --git a/cask/src/cask/endpoints/WebSocketEndpoint.scala b/cask/src/cask/endpoints/WebSocketEndpoint.scala index f747341..5f35832 100644 --- a/cask/src/cask/endpoints/WebSocketEndpoint.scala +++ b/cask/src/cask/endpoints/WebSocketEndpoint.scala @@ -3,22 +3,25 @@ package cask.endpoints import cask.internal.Router import cask.model.Request import io.undertow.websockets.WebSocketConnectionCallback - +import collection.JavaConverters._ sealed trait WebsocketResult object WebsocketResult{ - implicit class Response(val value: cask.model.Response) extends WebsocketResult + implicit class Response[T](value0: cask.model.Response[T]) + (implicit f: T => cask.model.Response.Data) extends WebsocketResult{ + def value = value0.map(f) + } implicit class Listener(val value: WebSocketConnectionCallback) extends WebsocketResult } class websocket(val path: String, override val subpath: Boolean = false) extends cask.main.BaseEndpoint{ - type Output = WebsocketResult + type InnerReturned = WebsocketResult val methods = Seq("websocket") type Input = Seq[String] type InputParser[T] = QueryParamReader[T] - type Returned = Router.Result[WebsocketResult] - def wrapFunction(ctx: Request, delegate: Delegate): Returned = delegate(Map()) + type OuterReturned = Router.Result[WebsocketResult] + def wrapFunction(ctx: Request, delegate: Delegate): OuterReturned = { + delegate(WebEndpoint.buildMapFromQueryParams(ctx)) + } def wrapPathSegment(s: String): Input = Seq(s) - - } |