diff options
author | Li Haoyi <haoyi.sg@gmail.com> | 2018-07-21 16:01:59 +0800 |
---|---|---|
committer | Li Haoyi <haoyi.sg@gmail.com> | 2018-07-21 16:04:56 +0800 |
commit | c1dcd6b5794bd1ceb3d92edc8a7f730c93098ef3 (patch) | |
tree | 3b6f37d73b48f5ae8c80fb51cb9aba2f8929bb10 | |
parent | 9da5084d27b1d5ed08e7d457817943cebe59580a (diff) | |
download | cask-c1dcd6b5794bd1ceb3d92edc8a7f730c93098ef3.tar.gz cask-c1dcd6b5794bd1ceb3d92edc8a7f730c93098ef3.tar.bz2 cask-c1dcd6b5794bd1ceb3d92edc8a7f730c93098ef3.zip |
Tidying up
-rw-r--r-- | cask/src/cask/Annotations.scala | 21 | ||||
-rw-r--r-- | cask/src/cask/Main.scala | 129 | ||||
-rw-r--r-- | cask/src/cask/ParamReader.scala | 23 | ||||
-rw-r--r-- | cask/src/cask/Routes.scala | 46 |
4 files changed, 114 insertions, 105 deletions
diff --git a/cask/src/cask/Annotations.scala b/cask/src/cask/Annotations.scala new file mode 100644 index 0000000..83534e6 --- /dev/null +++ b/cask/src/cask/Annotations.scala @@ -0,0 +1,21 @@ +package cask + +import scala.annotation.StaticAnnotation + + +trait AnnotationBase{ + def wrapMethodOutput(t: Response): Any + def parseMethodInput[T](implicit p: ParamReader[T]) = p +} +trait RouteBase extends AnnotationBase{ + val path: String + def wrapMethodOutput(t: Response) = t +} +class get(val path: String) extends StaticAnnotation with RouteBase +class post(val path: String) extends StaticAnnotation with RouteBase +class put(val path: String) extends StaticAnnotation with RouteBase +class route(val path: String, val methods: Seq[String]) extends StaticAnnotation with RouteBase + +class static(val path: String) extends StaticAnnotation{ + def wrapOutput(t: String) = t +} diff --git a/cask/src/cask/Main.scala b/cask/src/cask/Main.scala index b9a02de..1d86de1 100644 --- a/cask/src/cask/Main.scala +++ b/cask/src/cask/Main.scala @@ -18,78 +18,81 @@ abstract class BaseMain{ def servers: Seq[Routes] val port: Int = 8080 val host: String = "localhost" - def main(args: Array[String]): Unit = { - val allRoutes = for{ - server <- servers - route <- server.caskMetadata.value.map(x => x: Routes.RouteMetadata[_]) - } yield (server, route) - val server = Undertow.builder - .addHttpListener(port, host) - .setHandler(new BlockingHandler(new HttpHandler() { - def handleRequest(exchange: HttpServerExchange): Unit = { - val routeOpt = - allRoutes - .iterator - .map { case (s: Routes, r: Routes.RouteMetadata[_]) => - Util.matchRoute(r.metadata.path, exchange.getRequestPath).map((s, r, _)) - } - .flatten - .toStream - .headOption + val allRoutes = for{ + server <- servers + route <- server.caskMetadata.value.map(x => x: Routes.RouteMetadata[_]) + } yield (server, route) + val defaultHandler = new HttpHandler() { + def handleRequest(exchange: HttpServerExchange): Unit = { + val routeOpt = + allRoutes + .iterator + .map { case (s: Routes, r: Routes.RouteMetadata[_]) => + Util.matchRoute(r.metadata.path, exchange.getRequestPath).map((s, r, _)) + } + .flatten + .toStream + .headOption - routeOpt match{ - case None => - exchange.setStatusCode(404) - exchange.getResponseHeaders.put(Headers.CONTENT_TYPE, "text/plain") - exchange.getResponseSender.send("404 Not Found") - case Some((server, route, bindings)) => - import collection.JavaConverters._ - val allBindings = - bindings.toSeq ++ - exchange.getQueryParameters - .asScala - .toSeq - .flatMap{case (k, vs) => vs.asScala.map((k, _))} - - val result = route.entryPoint - .asInstanceOf[EntryPoint[server.type, HttpServerExchange]] - .invoke(server, exchange, allBindings.map{case (k, v) => (k, Some(v))}) - - result match{ - case Router.Result.Success(response: Response) => - response.headers.foreach{case (k, v) => - exchange.getResponseHeaders.put(new HttpString(k), v) - } + routeOpt match{ + case None => + + exchange.setStatusCode(404) + exchange.getResponseHeaders.put(Headers.CONTENT_TYPE, "text/plain") + exchange.getResponseSender.send("404 Not Found") + case Some((server, route, bindings)) => + import collection.JavaConverters._ + val allBindings = + bindings.toSeq ++ + exchange.getQueryParameters + .asScala + .toSeq + .flatMap{case (k, vs) => vs.asScala.map((k, _))} + + val result = route.entryPoint + .asInstanceOf[EntryPoint[server.type, HttpServerExchange]] + .invoke(server, exchange, allBindings.map{case (k, v) => (k, Some(v))}) - exchange.setStatusCode(response.statusCode) - - - response.data.write( - new OutputStream { - def write(b: Int) = { - exchange.getResponseSender.send(ByteBuffer.wrap(Array(b.toByte))) - } - override def write(b: Array[Byte]) = { - exchange.getResponseSender.send(ByteBuffer.wrap(b)) - } - override def write(b: Array[Byte], off: Int, len: Int) = { - exchange.getResponseSender.send(ByteBuffer.wrap(b.slice(off, off + len))) - } - } - ) - case err: Router.Result.Error => - exchange.setStatusCode(400) - exchange.getResponseHeaders.put(Headers.CONTENT_TYPE, "text/plain") - exchange.getResponseSender.send("400 Not Found " + result) + result match{ + case Router.Result.Success(response: Response) => + response.headers.foreach{case (k, v) => + exchange.getResponseHeaders.put(new HttpString(k), v) } + exchange.setStatusCode(response.statusCode) + + response.data.write( + new OutputStream { + def write(b: Int) = { + exchange.getResponseSender.send(ByteBuffer.wrap(Array(b.toByte))) + } + override def write(b: Array[Byte]) = { + exchange.getResponseSender.send(ByteBuffer.wrap(b)) + } + override def write(b: Array[Byte], off: Int, len: Int) = { + exchange.getResponseSender.send(ByteBuffer.wrap(b.slice(off, off + len))) + } + } + ) + case err: Router.Result.Error => + exchange.setStatusCode(400) + exchange.getResponseHeaders.put(Headers.CONTENT_TYPE, "text/plain") + exchange.getResponseSender.send("400 Not Found " + result) } - } - })) + + + } + } + } + + def main(args: Array[String]): Unit = { + val server = Undertow.builder + .addHttpListener(port, host) + .setHandler(new BlockingHandler(defaultHandler)) .build server.start() } diff --git a/cask/src/cask/ParamReader.scala b/cask/src/cask/ParamReader.scala new file mode 100644 index 0000000..8cb7c1f --- /dev/null +++ b/cask/src/cask/ParamReader.scala @@ -0,0 +1,23 @@ +package cask + +import io.undertow.server.HttpServerExchange + +class ParamReader[T](val arity: Int, + val read0: (HttpServerExchange, Seq[String]) => T) + extends Router.ArgReader[T, HttpServerExchange]{ + def read(ctx: HttpServerExchange, v: Seq[String]): T = read0(ctx, v) +} +object ParamReader{ + implicit object StringParam extends ParamReader[String](1, (h, x) => x.head) + implicit object BooleanParam extends ParamReader[Boolean](1, (h, x) => x.head.toBoolean) + implicit object ByteParam extends ParamReader[Byte](1, (h, x) => x.head.toByte) + implicit object ShortParam extends ParamReader[Short](1, (h, x) => x.head.toShort) + implicit object IntParam extends ParamReader[Int](1, (h, x) => x.head.toInt) + implicit object LongParam extends ParamReader[Long](1, (h, x) => x.head.toLong) + implicit object DoubleParam extends ParamReader[Double](1, (h, x) => x.head.toDouble) + implicit object FloatParam extends ParamReader[Float](1, (h, x) => x.head.toFloat) + implicit def SeqParam[T: ParamReader] = + new ParamReader[Seq[T]](1, (h, s) => s.map(x => implicitly[ParamReader[T]].read(h, Seq(x)))) + + implicit object HttpExchangeParam extends ParamReader[HttpServerExchange](0, (h, x) => h) +}
\ No newline at end of file diff --git a/cask/src/cask/Routes.scala b/cask/src/cask/Routes.scala index 757eb48..0e88a5e 100644 --- a/cask/src/cask/Routes.scala +++ b/cask/src/cask/Routes.scala @@ -5,47 +5,8 @@ import java.io.OutputStream import cask.Router.EntryPoint import io.undertow.server.HttpServerExchange -import scala.annotation.StaticAnnotation import scala.reflect.macros.blackbox.Context -class ParamType[T](val arity: Int, - val read0: (HttpServerExchange, Seq[String]) => T) - extends Router.ArgReader[T, HttpServerExchange]{ - def read(ctx: HttpServerExchange, v: Seq[String]): T = read0(ctx, v) -} -object ParamType{ - def findImplicitly[T](implicit p: ParamType[T]) = p - - implicit object StringParam extends ParamType[String](1, (h, x) => x.head) - implicit object BooleanParam extends ParamType[Boolean](1, (h, x) => x.head.toBoolean) - implicit object ByteParam extends ParamType[Byte](1, (h, x) => x.head.toByte) - implicit object ShortParam extends ParamType[Short](1, (h, x) => x.head.toShort) - implicit object IntParam extends ParamType[Int](1, (h, x) => x.head.toInt) - implicit object LongParam extends ParamType[Long](1, (h, x) => x.head.toLong) - implicit object DoubleParam extends ParamType[Double](1, (h, x) => x.head.toDouble) - implicit object FloatParam extends ParamType[Float](1, (h, x) => x.head.toFloat) - implicit def SeqParam[T: ParamType] = - new ParamType[Seq[T]](1, (h, s) => s.map(x => implicitly[ParamType[T]].read(h, Seq(x)))) - - implicit object HttpExchangeParam extends ParamType[HttpServerExchange](0, (h, x) => h) -} - -trait AnnotationBase{ - def wrapOutput(t: Response): Any -// def wrapInput(t: Response): Any -} -trait RouteBase extends AnnotationBase{ - val path: String - def wrapOutput(t: Response) = t -} -class get(val path: String) extends StaticAnnotation with RouteBase -class post(val path: String) extends StaticAnnotation with RouteBase -class put(val path: String) extends StaticAnnotation with RouteBase -class route(val path: String, val methods: Seq[String]) extends StaticAnnotation with RouteBase - -class static(val path: String) extends StaticAnnotation{ - def wrapOutput(t: String) = t -} case class Response(data: Response.Data, statusCode: Int = 200, @@ -80,15 +41,16 @@ object Routes{ annot <- m.annotations.filter(_.tree.tpe <:< c.weakTypeOf[RouteBase]) } yield { val annotObject = q"new ${annot.tree.tpe}(..${annot.tree.children.tail})" + val annotObjectSym = c.universe.TermName(c.freshName("annotObject")) val route = router.extractMethod( m.asInstanceOf[MethodSymbol], weakTypeOf[T], - (t: router.c.universe.Tree) => q"$annotObject.wrapOutput($t)", + (t: router.c.universe.Tree) => q"$annotObjectSym.wrapMethodOutput($t)", c.weakTypeOf[io.undertow.server.HttpServerExchange], - q"cask.ParamType.findImplicitly" + q"$annotObjectSym.parseMethodInput" ) - val annotObjectSym = c.universe.TermName(c.freshName("annotObject")) + q"""{ val $annotObjectSym = $annotObject cask.Routes.RouteMetadata($annotObjectSym, $route) |