diff options
-rw-r--r-- | build.sc | 10 | ||||
-rw-r--r-- | cask/src/cask/decorators/compress.scala | 5 | ||||
-rw-r--r-- | docs/pages/1 - Cask: a Scala HTTP micro-framework.md | 116 | ||||
-rw-r--r-- | example/todo/app/src/TodoServer.scala | 15 | ||||
-rw-r--r-- | example/todo/app/test/src/ExampleTests.scala | 2 | ||||
-rw-r--r-- | example/todo/build.sc | 2 | ||||
-rw-r--r-- | example/todoDb/app/src/TodoMvcDb.scala | 15 | ||||
-rw-r--r-- | example/todoDb/app/test/src/ExampleTests.scala | 2 | ||||
-rw-r--r-- | example/todoDb/build.sc | 2 |
9 files changed, 89 insertions, 80 deletions
@@ -17,7 +17,7 @@ import $file.example.scalatags.build import $file.example.staticFiles.build import $file.example.todo.build import $file.example.todoApi.build -//import $file.example.todoDb.build +import $file.example.todoDb.build import $file.example.twirl.build import $file.example.variableRoutes.build import $file.example.websockets.build @@ -115,9 +115,9 @@ object example extends Module{ object redirectAbort extends $file.example.redirectAbort.build.AppModule with LocalModule object scalatags extends $file.example.scalatags.build.AppModule with LocalModule object staticFiles extends $file.example.staticFiles.build.AppModule with LocalModule -// object todo extends $file.example.todo.build.AppModule with LocalModule + object todo extends $file.example.todo.build.AppModule with LocalModule object todoApi extends $file.example.todoApi.build.AppModule with LocalModule -// object todoDb extends $file.example.todoDb.build.AppModule with LocalModule + object todoDb extends $file.example.todoDb.build.AppModule with LocalModule object twirl extends $file.example.twirl.build.AppModule with LocalModule object variableRoutes extends $file.example.variableRoutes.build.AppModule with LocalModule object websockets extends $file.example.websockets.build.AppModule with LocalModule @@ -159,9 +159,9 @@ def uploadToGithub(authKey: String) = T.command{ $file.example.redirectAbort.build.millSourcePath, $file.example.scalatags.build.millSourcePath, $file.example.staticFiles.build.millSourcePath, -// $file.example.todo.build.millSourcePath, + $file.example.todo.build.millSourcePath, $file.example.todoApi.build.millSourcePath, -// $file.example.todoDb.build.millSourcePath, + $file.example.todoDb.build.millSourcePath, $file.example.twirl.build.millSourcePath, $file.example.variableRoutes.build.millSourcePath, $file.example.websockets.build.millSourcePath, diff --git a/cask/src/cask/decorators/compress.scala b/cask/src/cask/decorators/compress.scala index 0ffab28..3738bd0 100644 --- a/cask/src/cask/decorators/compress.scala +++ b/cask/src/cask/decorators/compress.scala @@ -7,7 +7,10 @@ import cask.model.{Request, Response} import collection.JavaConverters._ class compress extends cask.RawDecorator{ def wrapFunction(ctx: Request, delegate: Delegate) = { - val acceptEncodings = ctx.exchange.getRequestHeaders.get("Accept-Encoding").asScala.flatMap(_.split(", ")) + val acceptEncodings = Option(ctx.exchange.getRequestHeaders.get("Accept-Encoding")) + .toSeq + .flatMap(_.asScala) + .flatMap(_.split(", ")) delegate(Map()).map{ v => val (newData, newHeaders) = if (acceptEncodings.exists(_.toLowerCase == "gzip")) { new Response.Data { diff --git a/docs/pages/1 - Cask: a Scala HTTP micro-framework.md b/docs/pages/1 - Cask: a Scala HTTP micro-framework.md index 25126e7..aa878c6 100644 --- a/docs/pages/1 - Cask: a Scala HTTP micro-framework.md +++ b/docs/pages/1 - Cask: a Scala HTTP micro-framework.md @@ -391,61 +391,61 @@ etc.. Those can be managed via the normal mechanism for [Serving Static Files](#serving-static-files). -<!--## TodoMVC Database Integration--> - -<!--$$$todoDb--> - -<!--This example demonstrates how to use Cask to write a TodoMVC API server that--> -<!--persists it's state in a database rather than in memory. We use the--> -<!--[Quill](http://getquill.io/) database access library to write a `@transactional`--> -<!--decorator that automatically opens one transaction per call to an endpoint,--> -<!--ensuring that database queries are properly committed on success or rolled-back--> -<!--on error. Note that because the default database connector propagates its--> -<!--transaction context in a thread-local, `@transactional` does not need to pass--> -<!--the `ctx` object into each endpoint as an additional parameter list, and so we--> -<!--simply leave it out.--> - -<!--While this example is specific to Quill, you can easily modify the--> -<!--`@transactional` decorator to make it <!--## TodoMVC Database Integration--> - -<!--$$$todoDb--> - -<!--This example demonstrates how to use Cask to write a TodoMVC API server that--> -<!--persists it's state in a database rather than in memory. We use the--> -<!--[Quill](http://getquill.io/) database access library to write a `@transactional`--> -<!--decorator that automatically opens one transaction per call to an endpoint,--> -<!--ensuring that database queries are properly committed on success or rolled-back--> -<!--on error. Note that because the default database connector propagates its--> -<!--transaction context in a thread-local, `@transactional` does not need to pass--> -<!--the `ctx` object into each endpoint as an additional parameter list, and so we--> -<!--simply leave it out.--> - -<!--While this example is specific to Quill, you can easily modify the--> -<!--`@transactional` decorator to make it work with whatever database access library--> -<!--you happen to be using. For libraries which need an implicit transaction, it can--> -<!--be passed into each endpoint function as an additional parameter list as--> -<!--described in--> -<!--[Extending Endpoints with Decorators](#extending-endpoints-with-decorators).--> -<!--work with whatever database access library--> -<!--you happen to be using. For libraries which need an implicit transaction, it can--> -<!--be passed into each endpoint function as an additional parameter list as--> -<!--described in--> -<!--[Extending Endpoints with Decorators](#extending-endpoints-with-decorators).--> - -<!--## TodoMVC Full Stack Web--> - - -<!--The following code snippet is the complete code for a full-stack TodoMVC--> -<!--implementation: including HTML generation for the web UI via--> -<!--[Scalatags](https://github.com/lihaoyi/scalatags), Javascript for the--> -<!--interactivity, static file serving, and database integration via--> -<!--[Quill](https://github.com/getquill/quill). While slightly long, this example--> -<!--should give you a tour of all the things you need to know to use Cask.--> - -<!--Note that this is a "boring" server-side-rendered webapp with Ajax interactions,--> -<!--without any complex front-end frameworks or libraries: it's purpose is to--> -<!--demonstrate a simple working web application of using Cask end-to-end, which you--> -<!--can build upon to create your own Cask web application architected however you--> -<!--would like.--> - -<!--$$$todo--> +## TodoMVC Database Integration + +$$$todoDb + +This example demonstrates how to use Cask to write a TodoMVC API server that +persists it's state in a database rather than in memory. We use the +[Quill](http://getquill.io/) database access library to write a `@transactional` +decorator that automatically opens one transaction per call to an endpoint, +ensuring that database queries are properly committed on success or rolled-back +on error. Note that because the default database connector propagates its +transaction context in a thread-local, `@transactional` does not need to pass +the `ctx` object into each endpoint as an additional parameter list, and so we +simply leave it out. + +While this example is specific to Quill, you can easily modify the +`@transactional` decorator to make it <!--## TodoMVC Database Integration + +$$$todoDb + +This example demonstrates how to use Cask to write a TodoMVC API server that +persists it's state in a database rather than in memory. We use the +[Quill](http://getquill.io/) database access library to write a `@transactional` +decorator that automatically opens one transaction per call to an endpoint, +ensuring that database queries are properly committed on success or rolled-back +on error. Note that because the default database connector propagates its +transaction context in a thread-local, `@transactional` does not need to pass +the `ctx` object into each endpoint as an additional parameter list, and so we +simply leave it out. + +While this example is specific to Quill, you can easily modify the +`@transactional` decorator to make it work with whatever database access library +you happen to be using. For libraries which need an implicit transaction, it can +be passed into each endpoint function as an additional parameter list as +described in +[Extending Endpoints with Decorators](#extending-endpoints-with-decorators). +work with whatever database access library +you happen to be using. For libraries which need an implicit transaction, it can +be passed into each endpoint function as an additional parameter list as +described in +[Extending Endpoints with Decorators](#extending-endpoints-with-decorators). + +## TodoMVC Full Stack Web + + +The following code snippet is the complete code for a full-stack TodoMVC +implementation: including HTML generation for the web UI via +[Scalatags](https://github.com/lihaoyi/scalatags), Javascript for the +interactivity, static file serving, and database integration via +[Quill](https://github.com/getquill/quill). While slightly long, this example +should give you a tour of all the things you need to know to use Cask. + +Note that this is a "boring" server-side-rendered webapp with Ajax interactions, +without any complex front-end frameworks or libraries: it's purpose is to +demonstrate a simple working web application of using Cask end-to-end, which you +can build upon to create your own Cask web application architected however you +would like. + +$$$todo diff --git a/example/todo/app/src/TodoServer.scala b/example/todo/app/src/TodoServer.scala index 1a58d09..2df6fb2 100644 --- a/example/todo/app/src/TodoServer.scala +++ b/example/todo/app/src/TodoServer.scala @@ -1,5 +1,4 @@ package app -import cask.internal.Router import com.typesafe.config.ConfigFactory import io.getquill.{SnakeCase, SqliteJdbcContext} import scalatags.Text.all._ @@ -15,13 +14,13 @@ object TodoServer extends cask.MainRoutes{ ) ) - class transactional extends cask.Decorator{ - class TransactionFailed(val value: Router.Result.Error) extends Exception + class transactional extends cask.RawDecorator{ + class TransactionFailed(val value: cask.router.Result.Error) extends Exception def wrapFunction(pctx: cask.Request, delegate: Delegate): OuterReturned = { try ctx.transaction( delegate(Map()) match{ - case Router.Result.Success(t) => Router.Result.Success(t) - case e: Router.Result.Error => throw new TransactionFailed(e) + case cask.router.Result.Success(t) => cask.router.Result.Success(t) + case e: cask.router.Result.Error => throw new TransactionFailed(e) } ) catch{case e: TransactionFailed => e.value} @@ -55,7 +54,11 @@ object TodoServer extends cask.MainRoutes{ @cask.post("/add/:state") def add(state: String, request: cask.Request) = { val body = new String(request.readAllBytes()) - run(query[Todo].insert(_.checked -> lift(false), _.text -> lift(body)).returning(_.id)) + run( + query[Todo] + .insert(_.checked -> lift(false), _.text -> lift(body)) + .returningGenerated(_.id) + ) renderBody(state).render } diff --git a/example/todo/app/test/src/ExampleTests.scala b/example/todo/app/test/src/ExampleTests.scala index e1be23c..0c39c87 100644 --- a/example/todo/app/test/src/ExampleTests.scala +++ b/example/todo/app/test/src/ExampleTests.scala @@ -1,7 +1,7 @@ package app import utest._ object ExampleTests extends TestSuite{ - def withServer[T](example: cask.main.BaseMain)(f: String => T): T = { + def withServer[T](example: cask.main.Main)(f: String => T): T = { val server = io.undertow.Undertow.builder .addHttpListener(8080, "localhost") .setHandler(example.defaultHandler) diff --git a/example/todo/build.sc b/example/todo/build.sc index c5d5610..9bfe43b 100644 --- a/example/todo/build.sc +++ b/example/todo/build.sc @@ -5,7 +5,7 @@ trait AppModule extends ScalaModule{ def scalaVersion = "2.13.0" def ivyDeps = Agg[Dep]( ivy"org.xerial:sqlite-jdbc:3.18.0", - ivy"io.getquill::quill-jdbc:2.5.4", + ivy"io.getquill::quill-jdbc:3.4.10", ivy"com.lihaoyi::scalatags:0.7.0", ) diff --git a/example/todoDb/app/src/TodoMvcDb.scala b/example/todoDb/app/src/TodoMvcDb.scala index 669b2b8..0bb25c0 100644 --- a/example/todoDb/app/src/TodoMvcDb.scala +++ b/example/todoDb/app/src/TodoMvcDb.scala @@ -1,5 +1,4 @@ package app -import cask.internal.Router import com.typesafe.config.ConfigFactory import io.getquill.{SqliteJdbcContext, SnakeCase} @@ -14,13 +13,13 @@ object TodoMvcDb extends cask.MainRoutes{ ) ) - class transactional extends cask.Decorator{ - class TransactionFailed(val value: Router.Result.Error) extends Exception + class transactional extends cask.RawDecorator{ + class TransactionFailed(val value: cask.router.Result.Error) extends Exception def wrapFunction(pctx: cask.Request, delegate: Delegate): OuterReturned = { try ctx.transaction( delegate(Map()) match{ - case Router.Result.Success(t) => Router.Result.Success(t) - case e: Router.Result.Error => throw new TransactionFailed(e) + case cask.router.Result.Success(t) => cask.router.Result.Success(t) + case e: cask.router.Result.Error => throw new TransactionFailed(e) } ) catch{case e: TransactionFailed => e.value} @@ -65,7 +64,11 @@ object TodoMvcDb extends cask.MainRoutes{ @cask.post("/add") def add(request: cask.Request) = { val body = new String(request.readAllBytes()) - run(query[Todo].insert(_.checked -> lift(false), _.text -> lift(body)).returning(_.id)) + run( + query[Todo] + .insert(_.checked -> lift(false), _.text -> lift(body)) + .returningGenerated(_.id) + ) } @transactional diff --git a/example/todoDb/app/test/src/ExampleTests.scala b/example/todoDb/app/test/src/ExampleTests.scala index 77cbbb3..263ad9d 100644 --- a/example/todoDb/app/test/src/ExampleTests.scala +++ b/example/todoDb/app/test/src/ExampleTests.scala @@ -4,7 +4,7 @@ import io.undertow.Undertow import utest._ object ExampleTests extends TestSuite{ - def withServer[T](example: cask.main.BaseMain)(f: String => T): T = { + def withServer[T](example: cask.main.Main)(f: String => T): T = { val server = Undertow.builder .addHttpListener(8080, "localhost") .setHandler(example.defaultHandler) diff --git a/example/todoDb/build.sc b/example/todoDb/build.sc index 589af39..e0da112 100644 --- a/example/todoDb/build.sc +++ b/example/todoDb/build.sc @@ -5,7 +5,7 @@ trait AppModule extends ScalaModule{ def scalaVersion = "2.13.0" def ivyDeps = Agg[Dep]( ivy"org.xerial:sqlite-jdbc:3.18.0", - ivy"io.getquill::quill-jdbc:2.5.4" + ivy"io.getquill::quill-jdbc:3.4.10" ) object test extends Tests{ |