diff options
author | Li Haoyi <haoyi.sg@gmail.com> | 2018-07-25 19:19:35 +0800 |
---|---|---|
committer | Li Haoyi <haoyi.sg@gmail.com> | 2018-07-25 19:19:35 +0800 |
commit | b985aa5d25d97794b26402f936c4323f977c4073 (patch) | |
tree | 60041c73efe6b25eff96db7a67e260e2f9f6614d | |
parent | 072028c76efde19c459b35d9e2a6789f03baa1b0 (diff) | |
download | cask-b985aa5d25d97794b26402f936c4323f977c4073.tar.gz cask-b985aa5d25d97794b26402f936c4323f977c4073.tar.bz2 cask-b985aa5d25d97794b26402f936c4323f977c4073.zip |
HTTP method distinction now works, by generating parallel routing trees one-per-method
-rw-r--r-- | cask/src/cask/endpoints/FormEndpoint.scala | 1 | ||||
-rw-r--r-- | cask/src/cask/endpoints/JsonEndpoint.scala | 1 | ||||
-rw-r--r-- | cask/src/cask/endpoints/StaticEndpoints.scala | 1 | ||||
-rw-r--r-- | cask/src/cask/endpoints/WebEndpoints.scala | 12 | ||||
-rw-r--r-- | cask/src/cask/main/Main.scala | 18 | ||||
-rw-r--r-- | cask/src/cask/main/Routes.scala | 3 |
6 files changed, 25 insertions, 11 deletions
diff --git a/cask/src/cask/endpoints/FormEndpoint.scala b/cask/src/cask/endpoints/FormEndpoint.scala index 2c420e9..2b8cf25 100644 --- a/cask/src/cask/endpoints/FormEndpoint.scala +++ b/cask/src/cask/endpoints/FormEndpoint.scala @@ -36,6 +36,7 @@ object FormReader{ } } class postForm(val path: String, override val subpath: Boolean = false) extends Routes.Endpoint[Response]{ + val methods = Seq("post") type InputType = Seq[FormValue] def wrapMethodOutput(t: Response) = t def parseMethodInput[T](implicit p: FormReader[T]) = p diff --git a/cask/src/cask/endpoints/JsonEndpoint.scala b/cask/src/cask/endpoints/JsonEndpoint.scala index ffbe290..f172b2b 100644 --- a/cask/src/cask/endpoints/JsonEndpoint.scala +++ b/cask/src/cask/endpoints/JsonEndpoint.scala @@ -25,6 +25,7 @@ object JsReader{ } } class postJson(val path: String, override val subpath: Boolean = false) extends Routes.Endpoint[Response]{ + val methods = Seq("post") type InputType = ujson.Js.Value def wrapMethodOutput(t: Response) = t def parseMethodInput[T](implicit p: JsReader[T]) = p diff --git a/cask/src/cask/endpoints/StaticEndpoints.scala b/cask/src/cask/endpoints/StaticEndpoints.scala index 89e4f4a..937b9c2 100644 --- a/cask/src/cask/endpoints/StaticEndpoints.scala +++ b/cask/src/cask/endpoints/StaticEndpoints.scala @@ -6,6 +6,7 @@ import cask.main.Routes import cask.model.{BaseResponse, ParamContext} class static(val path: String) extends Routes.Endpoint[String] { + val methods = Seq("get") type InputType = Seq[String] override def subpath = true def wrapOutput(t: String) = t diff --git a/cask/src/cask/endpoints/WebEndpoints.scala b/cask/src/cask/endpoints/WebEndpoints.scala index ed93c6c..14c21ce 100644 --- a/cask/src/cask/endpoints/WebEndpoints.scala +++ b/cask/src/cask/endpoints/WebEndpoints.scala @@ -27,9 +27,15 @@ trait WebEndpoint extends Routes.Endpoint[BaseResponse]{ .asInstanceOf[Router.Result[BaseResponse]] } } -class get(val path: String, override val subpath: Boolean = false) extends WebEndpoint -class post(val path: String, override val subpath: Boolean = false) extends WebEndpoint -class put(val path: String, override val subpath: Boolean = false) extends WebEndpoint +class get(val path: String, override val subpath: Boolean = false) extends WebEndpoint{ + val methods = Seq("get") +} +class post(val path: String, override val subpath: Boolean = false) extends WebEndpoint{ + val methods = Seq("post") +} +class put(val path: String, override val subpath: Boolean = false) extends WebEndpoint{ + val methods = Seq("put") +} class route(val path: String, val methods: Seq[String], override val subpath: Boolean = false) extends WebEndpoint abstract class QueryParamReader[T] diff --git a/cask/src/cask/main/Main.scala b/cask/src/cask/main/Main.scala index 680dd04..f7789e3 100644 --- a/cask/src/cask/main/Main.scala +++ b/cask/src/cask/main/Main.scala @@ -25,10 +25,14 @@ abstract class BaseMain{ route <- routes.caskMetadata.value.map(x => x: Routes.EndpointMetadata[_]) } yield (routes, route) - lazy val routeTrie = DispatchTrie.construct[(Routes, Routes.EndpointMetadata[_])](0, - for((route, metadata) <- routeList) - yield (Util.splitPath(metadata.metadata.path): IndexedSeq[String], (route, metadata), metadata.metadata.subpath) - ) + + lazy val routeTries = Seq("get", "put", "post") + .map { method => + method -> DispatchTrie.construct[(Routes, Routes.EndpointMetadata[_])](0, + for ((route, metadata) <- routeList if metadata.endpoint.methods.contains(method)) + yield (Util.splitPath(metadata.endpoint.path): IndexedSeq[String], (route, metadata), metadata.endpoint.subpath) + ) + }.toMap def handleError(statusCode: Int): Response = { Response( @@ -154,13 +158,13 @@ abstract class BaseMain{ } lazy val defaultHandler = new HttpHandler() { def handleRequest(exchange: HttpServerExchange): Unit = { - routeTrie.lookup(Util.splitPath(exchange.getRequestPath).toList, Map()) match{ + routeTries(exchange.getRequestMethod.toString.toLowerCase()).lookup(Util.splitPath(exchange.getRequestPath).toList, Map()) match{ case None => writeResponse(exchange, handleError(404)) case Some(((routes, metadata), bindings, remaining)) => - val result = metadata.metadata.handle( + val result = metadata.endpoint.handle( ParamContext(exchange, remaining), bindings, routes, metadata.entryPoint.asInstanceOf[ - EntryPoint[metadata.metadata.InputType, cask.main.Routes, cask.model.ParamContext] + EntryPoint[metadata.endpoint.InputType, cask.main.Routes, cask.model.ParamContext] ] ) diff --git a/cask/src/cask/main/Routes.scala b/cask/src/cask/main/Routes.scala index 33964fa..ee2b2b9 100644 --- a/cask/src/cask/main/Routes.scala +++ b/cask/src/cask/main/Routes.scala @@ -12,6 +12,7 @@ object Routes{ trait Endpoint[R]{ type InputType val path: String + val methods: Seq[String] def subpath: Boolean = false def wrapMethodOutput(t: R): Any def handle(ctx: ParamContext, @@ -20,7 +21,7 @@ object Routes{ entryPoint: EntryPoint[InputType, Routes, cask.model.ParamContext]): Router.Result[BaseResponse] } - case class EndpointMetadata[T](metadata: Endpoint[_], + case class EndpointMetadata[T](endpoint: Endpoint[_], entryPoint: EntryPoint[_, T, ParamContext]) case class RoutesEndpointsMetadata[T](value: EndpointMetadata[T]*) object RoutesEndpointsMetadata{ |