diff options
author | Li Haoyi <haoyi.sg@gmail.com> | 2018-07-25 16:43:58 +0800 |
---|---|---|
committer | Li Haoyi <haoyi.sg@gmail.com> | 2018-07-25 16:43:58 +0800 |
commit | 62a140e340891c3b22fd9d457c8e48fc91e25020 (patch) | |
tree | 4648d07286e6c8151fc00bdaaaf428cb2e354b48 | |
parent | c4476471f4ff4b38c518b5478996bc178a129e6b (diff) | |
download | cask-62a140e340891c3b22fd9d457c8e48fc91e25020.tar.gz cask-62a140e340891c3b22fd9d457c8e48fc91e25020.tar.bz2 cask-62a140e340891c3b22fd9d457c8e48fc91e25020.zip |
Extract out `model.ParamContext`
-rw-r--r-- | cask/src/cask/endpoints/Endpoint.scala | 7 | ||||
-rw-r--r-- | cask/src/cask/endpoints/FormEndpoint.scala | 23 | ||||
-rw-r--r-- | cask/src/cask/endpoints/JsonEndpoint.scala | 17 | ||||
-rw-r--r-- | cask/src/cask/endpoints/ParamReader.scala | 20 | ||||
-rw-r--r-- | cask/src/cask/endpoints/Params.scala (renamed from cask/src/cask/model/FormValue.scala) | 27 | ||||
-rw-r--r-- | cask/src/cask/endpoints/StaticEndpoints.scala | 11 | ||||
-rw-r--r-- | cask/src/cask/endpoints/WebEndpoints.scala | 22 | ||||
-rw-r--r-- | cask/src/cask/main/Main.scala | 8 | ||||
-rw-r--r-- | cask/src/cask/main/Routes.scala | 5 | ||||
-rw-r--r-- | cask/src/cask/model/Cookie.scala | 1 | ||||
-rw-r--r-- | cask/src/cask/model/ParamContext.scala | 8 | ||||
-rw-r--r-- | cask/src/cask/model/Params.scala | 4 | ||||
-rw-r--r-- | cask/src/cask/package.scala | 14 | ||||
-rw-r--r-- | cask/test/src/test/cask/Cookies.scala | 9 |
14 files changed, 102 insertions, 74 deletions
diff --git a/cask/src/cask/endpoints/Endpoint.scala b/cask/src/cask/endpoints/Endpoint.scala index 5d69faa..d30f537 100644 --- a/cask/src/cask/endpoints/Endpoint.scala +++ b/cask/src/cask/endpoints/Endpoint.scala @@ -3,7 +3,7 @@ package cask.endpoints import cask.internal.Router import cask.internal.Router.EntryPoint import cask.main.Routes -import cask.model.BaseResponse +import cask.model.{BaseResponse, ParamContext} import io.undertow.server.HttpServerExchange trait Endpoint[R]{ @@ -11,9 +11,8 @@ trait Endpoint[R]{ val path: String def subpath: Boolean = false def wrapMethodOutput(t: R): Any - def handle(exchange: HttpServerExchange, - remaining: Seq[String], + def handle(ctx: ParamContext, bindings: Map[String, String], routes: Routes, - entryPoint: EntryPoint[InputType, Routes, (HttpServerExchange, Seq[String])]): Router.Result[BaseResponse] + entryPoint: EntryPoint[InputType, Routes, cask.model.ParamContext]): Router.Result[BaseResponse] }
\ No newline at end of file diff --git a/cask/src/cask/endpoints/FormEndpoint.scala b/cask/src/cask/endpoints/FormEndpoint.scala index 29265b9..1345489 100644 --- a/cask/src/cask/endpoints/FormEndpoint.scala +++ b/cask/src/cask/endpoints/FormEndpoint.scala @@ -3,49 +3,48 @@ package cask.endpoints import cask.internal.Router.EntryPoint import cask.internal.Router import cask.main.Routes -import cask.model.{FormValue, Response} +import cask.model.{ParamContext, Response} import io.undertow.server.HttpServerExchange import io.undertow.server.handlers.form.FormParserFactory import collection.JavaConverters._ -sealed trait FormReader[T] extends Router.ArgReader[Seq[FormValue], T, (HttpServerExchange, Seq[String])] +sealed trait FormReader[T] extends Router.ArgReader[Seq[FormValue], T, cask.model.ParamContext] object FormReader{ implicit def paramFormReader[T: QueryParamReader] = new FormReader[T]{ def arity = implicitly[QueryParamReader[T]].arity - def read(ctx: (HttpServerExchange, Seq[String]), input: Seq[FormValue]) = { + def read(ctx: cask.model.ParamContext, input: Seq[FormValue]) = { implicitly[QueryParamReader[T]].read(ctx, input.map(_.value)) } } implicit def formValueReader = new FormReader[FormValue]{ def arity = 1 - def read(ctx: (HttpServerExchange, Seq[String]), input: Seq[FormValue]) = input.head + def read(ctx: cask.model.ParamContext, input: Seq[FormValue]) = input.head } implicit def formValuesReader = new FormReader[Seq[FormValue]]{ def arity = 1 - def read(ctx: (HttpServerExchange, Seq[String]), input: Seq[FormValue]) = input + def read(ctx: cask.model.ParamContext, input: Seq[FormValue]) = input } implicit def formValueFileReader = new FormReader[FormValue.File]{ def arity = 1 - def read(ctx: (HttpServerExchange, Seq[String]), input: Seq[FormValue]) = input.head.asFile.get + def read(ctx: cask.model.ParamContext, input: Seq[FormValue]) = input.head.asFile.get } implicit def formValuesFileReader = new FormReader[Seq[FormValue.File]]{ def arity = 1 - def read(ctx: (HttpServerExchange, Seq[String]), input: Seq[FormValue]) = input.map(_.asFile.get) + def read(ctx: cask.model.ParamContext, input: Seq[FormValue]) = input.map(_.asFile.get) } } class postForm(val path: String, override val subpath: Boolean = false) extends Endpoint[Response]{ type InputType = Seq[FormValue] def wrapMethodOutput(t: Response) = t def parseMethodInput[T](implicit p: FormReader[T]) = p - def handle(exchange: HttpServerExchange, - remaining: Seq[String], + def handle(ctx: ParamContext, bindings: Map[String, String], routes: Routes, - entryPoint: EntryPoint[Seq[FormValue], Routes, (HttpServerExchange, Seq[String])]): Router.Result[Response] = { + entryPoint: EntryPoint[Seq[FormValue], Routes, cask.model.ParamContext]): Router.Result[Response] = { - val formData = FormParserFactory.builder().build().createParser(exchange).parseBlocking() + val formData = FormParserFactory.builder().build().createParser(ctx.exchange).parseBlocking() val formDataBindings = formData .iterator() @@ -56,7 +55,7 @@ class postForm(val path: String, override val subpath: Boolean = false) extends val pathBindings = bindings.map{case (k, v) => (k, Seq(new FormValue.Plain(v, new io.undertow.util.HeaderMap())))} - entryPoint.invoke(routes, (exchange, remaining), pathBindings ++ formDataBindings) + entryPoint.invoke(routes, ctx, pathBindings ++ formDataBindings) .asInstanceOf[Router.Result[Response]] } } diff --git a/cask/src/cask/endpoints/JsonEndpoint.scala b/cask/src/cask/endpoints/JsonEndpoint.scala index ca66f67..38e15fe 100644 --- a/cask/src/cask/endpoints/JsonEndpoint.scala +++ b/cask/src/cask/endpoints/JsonEndpoint.scala @@ -3,16 +3,16 @@ package cask.endpoints import cask.internal.Router import cask.internal.Router.EntryPoint import cask.main.Routes -import cask.model.Response +import cask.model.{ParamContext, Response} import io.undertow.server.HttpServerExchange -sealed trait JsReader[T] extends Router.ArgReader[ujson.Js.Value, T, (HttpServerExchange, Seq[String])] +sealed trait JsReader[T] extends Router.ArgReader[ujson.Js.Value, T, cask.model.ParamContext] object JsReader{ implicit def defaultJsReader[T: upickle.default.Reader] = new JsReader[T]{ def arity = 1 - def read(ctx: (HttpServerExchange, Seq[String]), input: ujson.Js.Value): T = { + def read(ctx: cask.model.ParamContext, input: ujson.Js.Value): T = { implicitly[upickle.default.Reader[T]].apply(input) } } @@ -20,7 +20,7 @@ object JsReader{ implicit def paramReader[T: ParamReader] = new JsReader[T] { override def arity = 0 - override def read(ctx: (HttpServerExchange, Seq[String]), v: ujson.Js.Value) = { + override def read(ctx: cask.model.ParamContext, v: ujson.Js.Value) = { implicitly[ParamReader[T]].read(ctx, Nil) } } @@ -29,18 +29,17 @@ class postJson(val path: String, override val subpath: Boolean = false) extends type InputType = ujson.Js.Value def wrapMethodOutput(t: Response) = t def parseMethodInput[T](implicit p: JsReader[T]) = p - def handle(exchange: HttpServerExchange, - remaining: Seq[String], + def handle(ctx: ParamContext, bindings: Map[String, String], routes: Routes, - entryPoint: EntryPoint[ujson.Js.Value, Routes, (HttpServerExchange, Seq[String])]): Router.Result[Response] = { + entryPoint: EntryPoint[ujson.Js.Value, Routes, cask.model.ParamContext]): Router.Result[Response] = { - val js = ujson.read(new String(exchange.getInputStream.readAllBytes())).asInstanceOf[ujson.Js.Obj] + val js = ujson.read(new String(ctx.exchange.getInputStream.readAllBytes())).asInstanceOf[ujson.Js.Obj] js.obj val allBindings = bindings.mapValues(ujson.Js.Str(_)) - entryPoint.invoke(routes, (exchange, remaining), js.obj.toMap ++ allBindings) + entryPoint.invoke(routes, ctx, js.obj.toMap ++ allBindings) .asInstanceOf[Router.Result[Response]] } } diff --git a/cask/src/cask/endpoints/ParamReader.scala b/cask/src/cask/endpoints/ParamReader.scala index a9d9a7f..21cf3d7 100644 --- a/cask/src/cask/endpoints/ParamReader.scala +++ b/cask/src/cask/endpoints/ParamReader.scala @@ -6,22 +6,18 @@ import io.undertow.server.HttpServerExchange import io.undertow.server.handlers.form.{FormData, FormParserFactory} abstract class ParamReader[T] - extends Router.ArgReader[Seq[String], T, (HttpServerExchange, Seq[String])]{ + extends Router.ArgReader[Seq[String], T, cask.model.ParamContext]{ def arity: Int - def read(ctx: (HttpServerExchange, Seq[String]), v: Seq[String]): T + def read(ctx: cask.model.ParamContext, v: Seq[String]): T } object ParamReader{ - class NilParam[T](f: (HttpServerExchange, Seq[String]) => T) extends ParamReader[T]{ + class NilParam[T](f: cask.model.ParamContext => T) extends ParamReader[T]{ def arity = 0 - def read(ctx: (HttpServerExchange, Seq[String]), v: Seq[String]): T = f(ctx._1, ctx._2) + def read(ctx: cask.model.ParamContext, v: Seq[String]): T = f(ctx) } - implicit object HttpExchangeParam extends NilParam[HttpServerExchange]((server, remaining) => server) - implicit object SubpathParam extends NilParam[cask.model.Subpath]((server, remaining) => new cask.model.Subpath(remaining)) - implicit object CookieParam extends NilParam[cask.model.Cookies]((server, remaining) => { - import collection.JavaConverters._ - new cask.model.Cookies(server.getRequestCookies.asScala.toMap.map{case (k, v) => (k, Cookie.fromUndertow(v))}) - }) - implicit object FormDataParam extends NilParam[FormData]((server, remaining) => - FormParserFactory.builder().build().createParser(server).parseBlocking() + implicit object HttpExchangeParam extends NilParam[HttpServerExchange](ctx => ctx.exchange) + + implicit object FormDataParam extends NilParam[FormData](ctx => + FormParserFactory.builder().build().createParser(ctx.exchange).parseBlocking() ) } diff --git a/cask/src/cask/model/FormValue.scala b/cask/src/cask/endpoints/Params.scala index 01c75a4..60691f8 100644 --- a/cask/src/cask/model/FormValue.scala +++ b/cask/src/cask/endpoints/Params.scala @@ -1,4 +1,29 @@ -package cask.model +package cask.endpoints + +import cask.Cookie +import cask.endpoints.ParamReader.NilParam + +class Subpath(val value: Seq[String]) +object Subpath{ + implicit object SubpathParam extends NilParam[Subpath](ctx => new Subpath(ctx.remaining)) + +} +class Cookies(val value: Map[String, Cookie]) +object Cookies{ + implicit object CookieParam extends NilParam[Cookies](ctx => { + import collection.JavaConverters._ + new Cookies(ctx.exchange.getRequestCookies.asScala.toMap.map{case (k, v) => (k, Cookie.fromUndertow(v))}) + }) +} +object CookieParam{ + implicit object SubpathParamParam extends NilParam[CookieParam](ctx => +// new CookieParam(ctx.exchange.getRequestCookies()) + ??? + ) +} + +case class CookieParam(cookie: Cookie) + object FormValue{ def fromUndertow(from: io.undertow.server.handlers.form.FormData.FormValue) = { diff --git a/cask/src/cask/endpoints/StaticEndpoints.scala b/cask/src/cask/endpoints/StaticEndpoints.scala index ed964b0..7302bbe 100644 --- a/cask/src/cask/endpoints/StaticEndpoints.scala +++ b/cask/src/cask/endpoints/StaticEndpoints.scala @@ -3,7 +3,7 @@ package cask.endpoints import cask.internal.Router import cask.internal.Router.EntryPoint import cask.main.Routes -import cask.model.BaseResponse +import cask.model.{BaseResponse, ParamContext} import io.undertow.server.HttpServerExchange class static(val path: String) extends Endpoint[String] { @@ -13,14 +13,13 @@ class static(val path: String) extends Endpoint[String] { def parseMethodInput[T](implicit p: QueryParamReader[T]) = p def wrapMethodOutput(t: String) = t - def handle(exchange: HttpServerExchange, - remaining: Seq[String], + def handle(ctx: ParamContext, bindings: Map[String, String], routes: Routes, - entryPoint: EntryPoint[Seq[String], Routes, (HttpServerExchange, Seq[String])]): Router.Result[BaseResponse] = { - entryPoint.invoke(routes, (exchange, remaining), Map()).asInstanceOf[Router.Result[String]] match{ + entryPoint: EntryPoint[Seq[String], Routes, cask.model.ParamContext]): Router.Result[BaseResponse] = { + entryPoint.invoke(routes, ctx, Map()).asInstanceOf[Router.Result[String]] match{ case Router.Result.Success(s) => - Router.Result.Success(cask.model.Static(s + "/" + remaining.mkString("/"))) + Router.Result.Success(cask.model.Static(s + "/" + ctx.remaining.mkString("/"))) case e: Router.Result.Error => e diff --git a/cask/src/cask/endpoints/WebEndpoints.scala b/cask/src/cask/endpoints/WebEndpoints.scala index af2ed0a..ddef543 100644 --- a/cask/src/cask/endpoints/WebEndpoints.scala +++ b/cask/src/cask/endpoints/WebEndpoints.scala @@ -3,8 +3,7 @@ package cask.endpoints import cask.internal.Router import cask.internal.Router.EntryPoint import cask.main.Routes -import cask.model.BaseResponse -import io.undertow.server.HttpServerExchange +import cask.model.{BaseResponse, ParamContext} import collection.JavaConverters._ @@ -13,19 +12,18 @@ trait WebEndpoint extends Endpoint[BaseResponse]{ type InputType = Seq[String] def wrapMethodOutput(t: BaseResponse) = t def parseMethodInput[T](implicit p: QueryParamReader[T]) = p - def handle(exchange: HttpServerExchange, - remaining: Seq[String], + def handle(ctx: ParamContext, bindings: Map[String, String], routes: Routes, - entryPoint: EntryPoint[Seq[String], Routes, (HttpServerExchange, Seq[String])]): Router.Result[BaseResponse] = { + entryPoint: EntryPoint[Seq[String], Routes, cask.model.ParamContext]): Router.Result[BaseResponse] = { val allBindings = bindings.map{case (k, v) => (k, Seq(v))} ++ - exchange.getQueryParameters + ctx.exchange.getQueryParameters .asScala .toSeq .map{case (k, vs) => (k, vs.asScala.toArray.toSeq)} - entryPoint.invoke(routes, (exchange, remaining), allBindings) + entryPoint.invoke(routes, ctx, allBindings) .asInstanceOf[Router.Result[BaseResponse]] } } @@ -35,14 +33,14 @@ class put(val path: String, override val subpath: Boolean = false) extends WebEn class route(val path: String, val methods: Seq[String], override val subpath: Boolean = false) extends WebEndpoint abstract class QueryParamReader[T] - extends Router.ArgReader[Seq[String], T, (HttpServerExchange, Seq[String])]{ + extends Router.ArgReader[Seq[String], T, cask.model.ParamContext]{ def arity: Int - def read(ctx: (HttpServerExchange, Seq[String]), v: Seq[String]): T + def read(ctx: cask.model.ParamContext, v: Seq[String]): T } object QueryParamReader{ class SimpleParam[T](f: String => T) extends QueryParamReader[T]{ def arity = 1 - def read(ctx: (HttpServerExchange, Seq[String]), v: Seq[String]): T = f(v.head) + def read(ctx: cask.model.ParamContext, v: Seq[String]): T = f(v.head) } implicit object StringParam extends SimpleParam[String](x => x) @@ -55,14 +53,14 @@ object QueryParamReader{ implicit object FloatParam extends SimpleParam[Float](_.toFloat) implicit def SeqParam[T: QueryParamReader] = new QueryParamReader[Seq[T]]{ def arity = 1 - def read(ctx: (HttpServerExchange, Seq[String]), v: Seq[String]): Seq[T] = { + def read(ctx: cask.model.ParamContext, v: Seq[String]): Seq[T] = { v.map(x => implicitly[QueryParamReader[T]].read(ctx, Seq(x))) } } implicit def paramReader[T: ParamReader] = new QueryParamReader[T] { override def arity = 0 - override def read(ctx: (HttpServerExchange, Seq[String]), v: Seq[String]) = { + override def read(ctx: cask.model.ParamContext, v: Seq[String]) = { implicitly[ParamReader[T]].read(ctx, v) } } diff --git a/cask/src/cask/main/Main.scala b/cask/src/cask/main/Main.scala index 77bac94..28c7770 100644 --- a/cask/src/cask/main/Main.scala +++ b/cask/src/cask/main/Main.scala @@ -1,6 +1,6 @@ package cask.main -import cask.model.{BaseResponse, Response, Status} +import cask.model.{BaseResponse, ParamContext, Response, Status} import cask.Cookie import cask.internal.Router.EntryPoint import cask.internal.{DispatchTrie, Router, Util} @@ -54,8 +54,10 @@ abstract class BaseMain{ case None => writeResponse(exchange, handleError(404)) case Some(((routes, metadata), bindings, remaining)) => val result = metadata.metadata.handle( - exchange, remaining, bindings, routes, - metadata.entryPoint.asInstanceOf[EntryPoint[metadata.metadata.InputType, cask.main.Routes, (HttpServerExchange, Seq[String])]] + ParamContext(exchange, remaining), bindings, routes, + metadata.entryPoint.asInstanceOf[ + EntryPoint[metadata.metadata.InputType, cask.main.Routes, cask.model.ParamContext] + ] ) result match{ diff --git a/cask/src/cask/main/Routes.scala b/cask/src/cask/main/Routes.scala index fdd39bd..d3c060b 100644 --- a/cask/src/cask/main/Routes.scala +++ b/cask/src/cask/main/Routes.scala @@ -2,6 +2,7 @@ package cask.main import cask.endpoints.Endpoint import cask.internal.Router.EntryPoint +import cask.model.ParamContext import io.undertow.server.HttpServerExchange import scala.reflect.macros.blackbox.Context @@ -9,7 +10,7 @@ import language.experimental.macros object Routes{ case class EndpointMetadata[T](metadata: Endpoint[_], - entryPoint: EntryPoint[_, T, (HttpServerExchange, Seq[String])]) + entryPoint: EntryPoint[_, T, ParamContext]) case class RoutesEndpointsMetadata[T](value: EndpointMetadata[T]*) object RoutesEndpointsMetadata{ implicit def initialize[T] = macro initializeImpl[T] @@ -27,7 +28,7 @@ object Routes{ m.asInstanceOf[MethodSymbol], weakTypeOf[T], (t: router.c.universe.Tree) => q"$annotObjectSym.wrapMethodOutput($t)", - c.weakTypeOf[(io.undertow.server.HttpServerExchange, Seq[String])], + c.weakTypeOf[ParamContext], q"$annotObjectSym.parseMethodInput", tq"$annotObjectSym.InputType" ) diff --git a/cask/src/cask/model/Cookie.scala b/cask/src/cask/model/Cookie.scala index 119ea66..4934e87 100644 --- a/cask/src/cask/model/Cookie.scala +++ b/cask/src/cask/model/Cookie.scala @@ -2,6 +2,7 @@ package cask.model import io.undertow.server.handlers.CookieImpl + object Cookie{ def fromUndertow(from: io.undertow.server.handlers.Cookie): Cookie = { Cookie( diff --git a/cask/src/cask/model/ParamContext.scala b/cask/src/cask/model/ParamContext.scala new file mode 100644 index 0000000..d9f8cfc --- /dev/null +++ b/cask/src/cask/model/ParamContext.scala @@ -0,0 +1,8 @@ +package cask.model + +import io.undertow.server.HttpServerExchange + +case class ParamContext(exchange: HttpServerExchange, remaining: Seq[String]) { + + +} diff --git a/cask/src/cask/model/Params.scala b/cask/src/cask/model/Params.scala deleted file mode 100644 index f64fd87..0000000 --- a/cask/src/cask/model/Params.scala +++ /dev/null @@ -1,4 +0,0 @@ -package cask.model - -class Subpath(val value: Seq[String]) -class Cookies(val value: Map[String, Cookie])
\ No newline at end of file diff --git a/cask/src/cask/package.scala b/cask/src/cask/package.scala index fddb1e0..37ea5d9 100644 --- a/cask/src/cask/package.scala +++ b/cask/src/cask/package.scala @@ -6,12 +6,8 @@ package object cask { val Abort = model.Abort type Redirect = model.Redirect val Redirect = model.Redirect - type FormValue = model.FormValue - val FormValue = model.FormValue type Cookie = model.Cookie val Cookie = model.Cookie - type Cookies = model.Cookies - type Subpath = model.Subpath // endpoints type get = endpoints.get @@ -22,6 +18,16 @@ package object cask { type postJson = endpoints.postJson type postForm = endpoints.postForm + // endpoints misc + type FormValue = endpoints.FormValue + val FormValue = endpoints.FormValue + type Cookies = endpoints.Cookies + val Cookies = endpoints.Cookies + type Subpath = endpoints.Subpath + val Subpath = endpoints.Subpath + type CookieParam = endpoints.CookieParam + val CookieParam = endpoints.CookieParam + // main type MainRoutes = main.MainRoutes type Routes = main.Routes diff --git a/cask/test/src/test/cask/Cookies.scala b/cask/test/src/test/cask/Cookies.scala index 3cf1941..123d6a9 100644 --- a/cask/test/src/test/cask/Cookies.scala +++ b/cask/test/src/test/cask/Cookies.scala @@ -2,16 +2,15 @@ package test.cask object Cookies extends cask.MainRoutes{ @cask.get("/read-cookie") - def readCookies(cookies: cask.Cookies) = { - val username = cookies.value.get("my-username") - username.map(_.value).toString + def readCookies(username: cask.CookieParam) = { + username.cookie.value } @cask.get("/store-cookie") def storeCookies() = { cask.Response( "Cookies Set!", - cookies = Seq(cask.Cookie("my-username", "the username")) + cookies = Seq(cask.Cookie("username", "the username")) ) } @@ -19,7 +18,7 @@ object Cookies extends cask.MainRoutes{ def deleteCookie() = { cask.Response( "Cookies Deleted!", - cookies = Seq(cask.Cookie("my-username", "the username", expires = java.time.Instant.EPOCH)) + cookies = Seq(cask.Cookie("username", "the username", expires = java.time.Instant.EPOCH)) ) } |