From 8b14cd206e008b4001f9b257f48870c8d40e8498 Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Sat, 28 Jul 2018 19:38:43 +0800 Subject: first pass at a readme --- cask/src/cask/endpoints/FormEndpoint.scala | 35 +++++++++++++-------- cask/src/cask/model/Params.scala | 36 ++++++++++++---------- cask/src/cask/package.scala | 4 +++ cask/test/src/test/cask/Decorated.scala | 2 +- cask/test/src/test/cask/ExampleTests.scala | 25 ++++++++------- cask/test/src/test/cask/FormJsonPost.scala | 9 ++++-- cask/test/src/test/cask/MultipartFileUploads.scala | 16 ---------- cask/test/src/test/cask/VariableRoutes.scala | 4 +-- 8 files changed, 67 insertions(+), 64 deletions(-) delete mode 100644 cask/test/src/test/cask/MultipartFileUploads.scala (limited to 'cask') diff --git a/cask/src/cask/endpoints/FormEndpoint.scala b/cask/src/cask/endpoints/FormEndpoint.scala index c58c765..715c803 100644 --- a/cask/src/cask/endpoints/FormEndpoint.scala +++ b/cask/src/cask/endpoints/FormEndpoint.scala @@ -2,42 +2,51 @@ package cask.endpoints import cask.internal.{Router, Util} import cask.main.{Endpoint, Routes} -import cask.model.{FormValue, ParamContext, Response} +import cask.model._ import io.undertow.server.handlers.form.FormParserFactory import collection.JavaConverters._ -sealed trait FormReader[T] extends Router.ArgReader[Seq[FormValue], T, ParamContext] +sealed trait FormReader[T] extends Router.ArgReader[Seq[FormEntry], T, ParamContext] object FormReader{ implicit def paramFormReader[T: QueryParamReader] = new FormReader[T]{ def arity = implicitly[QueryParamReader[T]].arity - def read(ctx: ParamContext, label: String, input: Seq[FormValue]) = { - implicitly[QueryParamReader[T]].read(ctx, label, if (input == null) null else input.map(_.value)) + def read(ctx: ParamContext, label: String, input: Seq[FormEntry]) = { + implicitly[QueryParamReader[T]].read(ctx, label, if (input == null) null else input.map(_.valueOrFileName)) } } + implicit def formEntryReader = new FormReader[FormEntry]{ + def arity = 1 + def read(ctx: ParamContext, label: String, input: Seq[FormEntry]) = input.head + } + implicit def formEntriesReader = new FormReader[Seq[FormEntry]]{ + def arity = 1 + def read(ctx: ParamContext, label: String, input: Seq[FormEntry]) = input + } + implicit def formValueReader = new FormReader[FormValue]{ def arity = 1 - def read(ctx: ParamContext, label: String, input: Seq[FormValue]) = input.head + def read(ctx: ParamContext, label: String, input: Seq[FormEntry]) = input.head.asInstanceOf[FormValue] } implicit def formValuesReader = new FormReader[Seq[FormValue]]{ def arity = 1 - def read(ctx: ParamContext, label: String, input: Seq[FormValue]) = input + def read(ctx: ParamContext, label: String, input: Seq[FormEntry]) = input.map(_.asInstanceOf[FormValue]) } - implicit def formValueFileReader = new FormReader[FormValue.File]{ + implicit def formFileReader = new FormReader[FormFile]{ def arity = 1 - def read(ctx: ParamContext, label: String, input: Seq[FormValue]) = input.head.asFile.get + def read(ctx: ParamContext, label: String, input: Seq[FormEntry]) = input.head.asInstanceOf[FormFile] } - implicit def formValuesFileReader = new FormReader[Seq[FormValue.File]]{ + implicit def formFilesReader = new FormReader[Seq[FormFile]]{ def arity = 1 - def read(ctx: ParamContext, label: String, input: Seq[FormValue]) = input.map(_.asFile.get) + def read(ctx: ParamContext, label: String, input: Seq[FormEntry]) = input.map(_.asInstanceOf[FormFile]) } } class postForm(val path: String, override val subpath: Boolean = false) extends Endpoint[Response]{ val methods = Seq("post") - type Input = Seq[FormValue] + type Input = Seq[FormEntry] type InputParser[T] = FormReader[T] def getRawParams(ctx: ParamContext) = { for{ @@ -51,11 +60,11 @@ class postForm(val path: String, override val subpath: Boolean = false) extends formData .iterator() .asScala - .map(k => (k, formData.get(k).asScala.map(FormValue.fromUndertow).toSeq)) + .map(k => (k, formData.get(k).asScala.map(FormEntry.fromUndertow).toSeq)) .toMap formDataBindings } } - def wrapPathSegment(s: String): Input = Seq(FormValue.Plain(s, new io.undertow.util.HeaderMap)) + def wrapPathSegment(s: String): Input = Seq(FormValue(s, new io.undertow.util.HeaderMap)) } diff --git a/cask/src/cask/model/Params.scala b/cask/src/cask/model/Params.scala index 8f206c8..901cca4 100644 --- a/cask/src/cask/model/Params.scala +++ b/cask/src/cask/model/Params.scala @@ -76,24 +76,28 @@ case class Cookie(name: String, } -object FormValue{ +sealed trait FormEntry{ + def valueOrFileName: String + def headers: io.undertow.util.HeaderMap + def asFile: Option[FormFile] = this match{ + case p: FormValue => None + case p: FormFile => Some(p) + } +} +object FormEntry{ def fromUndertow(from: io.undertow.server.handlers.form.FormData.FormValue) = { - if (!from.isFile) Plain(from.getValue, from.getHeaders) - else File(from.getValue, from.getFileName, from.getPath, from.getHeaders) + if (!from.isFile) FormValue(from.getValue, from.getHeaders) + else FormFile(from.getFileName, from.getPath, from.getHeaders) } - case class Plain(value: String, - headers: io.undertow.util.HeaderMap) extends FormValue - case class File(value: String, - fileName: String, - filePath: java.nio.file.Path, - headers: io.undertow.util.HeaderMap) extends FormValue } -sealed trait FormValue{ - def value: String - def headers: io.undertow.util.HeaderMap - def asFile: Option[FormValue.File] = this match{ - case p: FormValue.Plain => None - case p: FormValue.File => Some(p) - } +case class FormValue(value: String, + headers: io.undertow.util.HeaderMap) extends FormEntry{ + def valueOrFileName = value +} + +case class FormFile(fileName: String, + filePath: java.nio.file.Path, + headers: io.undertow.util.HeaderMap) extends FormEntry{ + def valueOrFileName = fileName } diff --git a/cask/src/cask/package.scala b/cask/src/cask/package.scala index 37e61e2..24a0a20 100644 --- a/cask/src/cask/package.scala +++ b/cask/src/cask/package.scala @@ -6,8 +6,12 @@ package object cask { val Abort = model.Abort type Redirect = model.Redirect val Redirect = model.Redirect + type FormEntry = model.FormEntry + val FormEntry = model.FormEntry type FormValue = model.FormValue val FormValue = model.FormValue + type FormFile = model.FormFile + val FormFile = model.FormFile type Cookie = model.Cookie val Cookie = model.Cookie type Subpath = model.Subpath diff --git a/cask/test/src/test/cask/Decorated.scala b/cask/test/src/test/cask/Decorated.scala index bd27647..ed377cf 100644 --- a/cask/test/src/test/cask/Decorated.scala +++ b/cask/test/src/test/cask/Decorated.scala @@ -1,6 +1,6 @@ package test.cask -import cask.model.ParamContext +import cask.model.ParamContext object Decorated extends cask.MainRoutes{ class User{ diff --git a/cask/test/src/test/cask/ExampleTests.scala b/cask/test/src/test/cask/ExampleTests.scala index e5be3bf..1a5cf23 100644 --- a/cask/test/src/test/cask/ExampleTests.scala +++ b/cask/test/src/test/cask/ExampleTests.scala @@ -38,17 +38,17 @@ object ExampleTests extends TestSuite{ requests.get(host + "/user").statusCode ==> 404 - requests.get(host + "/post/123?query=xyz&query=abc").text() ==> + requests.get(host + "/post/123?param=xyz¶m=abc").text() ==> "Post 123 ArrayBuffer(xyz, abc)" requests.get(host + "/post/123").text() ==> - """Missing argument: (query: Seq[String]) + """Missing argument: (param: Seq[String]) | |Arguments provided did not match expected signature: | |showPost | postId Int - | query Seq[String] + | param Seq[String] | |""".stripMargin @@ -67,15 +67,6 @@ object ExampleTests extends TestSuite{ resp.history.get.statusCode ==> 301 } - 'MultipartFileUploads - test(MultipartFileUploads){ host => - val resp = requests.post( - host + "/upload", - data = requests.MultiPart( - requests.MultiItem("image", "...", "my-best-image.txt") - ) - ) - resp.text() ==> "my-best-image.txt" - } 'FormJsonPost - test(FormJsonPost){ host => requests.post(host + "/json", data = """{"value1": true, "value2": [3]}""").text() ==> "OK true Vector(3)" @@ -84,7 +75,15 @@ object ExampleTests extends TestSuite{ host + "/form", data = Seq("value1" -> "hello", "value2" -> "1", "value2" -> "2") ).text() ==> - "OK Plain(hello,null) List(1, 2)" + "OK FormValue(hello,null) List(1, 2)" + + val resp = requests.post( + host + "/upload", + data = requests.MultiPart( + requests.MultiItem("image", "...", "my-best-image.txt") + ) + ) + resp.text() ==> "my-best-image.txt" } 'Decorated - test(Decorated){ host => requests.get(host + "/hello/woo").text() ==> "woo31337" diff --git a/cask/test/src/test/cask/FormJsonPost.scala b/cask/test/src/test/cask/FormJsonPost.scala index 0be4480..9db3d24 100644 --- a/cask/test/src/test/cask/FormJsonPost.scala +++ b/cask/test/src/test/cask/FormJsonPost.scala @@ -1,7 +1,5 @@ package test.cask -import cask.FormValue - object FormJsonPost extends cask.MainRoutes{ @cask.postJson("/json") def jsonEndpoint(value1: ujson.Js.Value, value2: Seq[Int]) = { @@ -9,10 +7,15 @@ object FormJsonPost extends cask.MainRoutes{ } @cask.postForm("/form") - def formEndpoint(value1: FormValue, value2: Seq[Int]) = { + def formEndpoint(value1: cask.FormValue, value2: Seq[Int]) = { "OK " + value1 + " " + value2 } + @cask.postForm("/upload") + def uploadFile(image: cask.FormFile) = { + image.fileName + } + initialize() } diff --git a/cask/test/src/test/cask/MultipartFileUploads.scala b/cask/test/src/test/cask/MultipartFileUploads.scala deleted file mode 100644 index 11b6ec6..0000000 --- a/cask/test/src/test/cask/MultipartFileUploads.scala +++ /dev/null @@ -1,16 +0,0 @@ -package test.cask - -import io.undertow.server.HttpServerExchange -import io.undertow.server.handlers.form.FormData - -object MultipartFileUploads extends cask.MainRoutes{ - // curl -F "image=@build.sc" localhost:8080/upload - @cask.post("/upload") - def uploadFile(formData: FormData) = { - val file = formData.getFirst("image") - file.getFileName - } - - initialize() -} - diff --git a/cask/test/src/test/cask/VariableRoutes.scala b/cask/test/src/test/cask/VariableRoutes.scala index d1816ab..c997d39 100644 --- a/cask/test/src/test/cask/VariableRoutes.scala +++ b/cask/test/src/test/cask/VariableRoutes.scala @@ -7,8 +7,8 @@ object VariableRoutes extends cask.MainRoutes{ } @cask.get("/post/:postId") - def showPost(postId: Int, query: Seq[String]) = { - s"Post $postId $query" + def showPost(postId: Int, param: Seq[String]) = { + s"Post $postId $param" } @cask.get("/path", subpath = true) -- cgit v1.2.3