From c4ccbb44d760aa3eb8a260aafa8ccf557ba06d3f Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Wed, 25 Jul 2018 17:26:42 +0800 Subject: Create `requests: Requests` NilParam with convenience methods for common necessities --- cask/src/cask/endpoints/FormEndpoint.scala | 7 +- cask/src/cask/endpoints/JsonEndpoint.scala | 1 - cask/src/cask/endpoints/Params.scala | 79 ------------------- cask/src/cask/endpoints/StaticEndpoints.scala | 1 - cask/src/cask/main/Main.scala | 4 +- cask/src/cask/model/Params.scala | 99 ++++++++++++++++++++++++ cask/src/cask/model/Response.scala | 7 +- cask/src/cask/package.scala | 16 ++-- cask/test/src/test/cask/MinimalApplication.scala | 7 ++ 9 files changed, 121 insertions(+), 100 deletions(-) delete mode 100644 cask/src/cask/endpoints/Params.scala create mode 100644 cask/src/cask/model/Params.scala diff --git a/cask/src/cask/endpoints/FormEndpoint.scala b/cask/src/cask/endpoints/FormEndpoint.scala index 55614b2..2c420e9 100644 --- a/cask/src/cask/endpoints/FormEndpoint.scala +++ b/cask/src/cask/endpoints/FormEndpoint.scala @@ -1,12 +1,10 @@ package cask.endpoints -import cask.endpoints.ParamReader.NilParam import cask.internal.Router.EntryPoint import cask.internal.Router import cask.main.Routes -import cask.model.{ParamContext, Response} -import io.undertow.server.HttpServerExchange -import io.undertow.server.handlers.form.{FormData, FormParserFactory} +import cask.model.{FormValue, ParamContext, Response} +import io.undertow.server.handlers.form.{FormParserFactory} import collection.JavaConverters._ @@ -61,3 +59,4 @@ class postForm(val path: String, override val subpath: Boolean = false) extends .asInstanceOf[Router.Result[Response]] } } + diff --git a/cask/src/cask/endpoints/JsonEndpoint.scala b/cask/src/cask/endpoints/JsonEndpoint.scala index 68a66e6..ffbe290 100644 --- a/cask/src/cask/endpoints/JsonEndpoint.scala +++ b/cask/src/cask/endpoints/JsonEndpoint.scala @@ -4,7 +4,6 @@ import cask.internal.Router import cask.internal.Router.EntryPoint import cask.main.Routes import cask.model.{ParamContext, Response} -import io.undertow.server.HttpServerExchange sealed trait JsReader[T] extends Router.ArgReader[ujson.Js.Value, T, cask.model.ParamContext] diff --git a/cask/src/cask/endpoints/Params.scala b/cask/src/cask/endpoints/Params.scala deleted file mode 100644 index 7a56085..0000000 --- a/cask/src/cask/endpoints/Params.scala +++ /dev/null @@ -1,79 +0,0 @@ -package cask.endpoints - -import cask.endpoints.ParamReader.NilParam -import io.undertow.server.handlers.CookieImpl - -class Subpath(val value: Seq[String]) -object Subpath{ - implicit object SubpathParam extends NilParam[Subpath]((ctx, label) => new Subpath(ctx.remaining)) -} - - -object Cookie{ - implicit object CookieParam extends NilParam[Cookie]((ctx, label) => - Cookie.fromUndertow(ctx.exchange.getRequestCookies().get(label)) - ) - def fromUndertow(from: io.undertow.server.handlers.Cookie): Cookie = { - Cookie( - from.getName, - from.getValue, - from.getComment, - from.getDomain, - if (from.getExpires == null) null else from.getExpires.toInstant, - from.getMaxAge, - from.getPath, - from.getVersion, - from.isDiscard, - from.isHttpOnly, - from.isSecure - ) - } - def toUndertow(from: Cookie): io.undertow.server.handlers.Cookie = { - val out = new CookieImpl(from.name, from.value) - out.setComment(from.comment) - out.setDomain(from.domain) - out.setExpires(if (from.expires == null) null else java.util.Date.from(from.expires)) - out.setMaxAge(from.maxAge) - out.setPath(from.path) - out.setVersion(from.version) - out.setDiscard(from.discard) - out.setHttpOnly(from.httpOnly) - out.setSecure(from.secure) - } -} -case class Cookie(name: String, - value: String, - comment: String = null, - domain: String = null, - expires: java.time.Instant = null, - maxAge: Integer = null, - path: String = null, - version: Int = 1, - discard: Boolean = false, - httpOnly: Boolean = false, - secure: Boolean = false) { - -} - - -object FormValue{ - 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) - } - 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) - } -} diff --git a/cask/src/cask/endpoints/StaticEndpoints.scala b/cask/src/cask/endpoints/StaticEndpoints.scala index 32d499b..89e4f4a 100644 --- a/cask/src/cask/endpoints/StaticEndpoints.scala +++ b/cask/src/cask/endpoints/StaticEndpoints.scala @@ -4,7 +4,6 @@ import cask.internal.Router import cask.internal.Router.EntryPoint import cask.main.Routes import cask.model.{BaseResponse, ParamContext} -import io.undertow.server.HttpServerExchange class static(val path: String) extends Routes.Endpoint[String] { type InputType = Seq[String] diff --git a/cask/src/cask/main/Main.scala b/cask/src/cask/main/Main.scala index ac2d8dc..045c2ed 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, ParamContext, Response, Status} +import cask.model._ import cask.internal.Router.EntryPoint import cask.internal.{DispatchTrie, Router, Util} import io.undertow.Undertow @@ -41,7 +41,7 @@ abstract class BaseMain{ response.headers.foreach{case (k, v) => exchange.getResponseHeaders.put(new HttpString(k), v) } - response.cookies.foreach(c => exchange.setResponseCookie(cask.endpoints.Cookie.toUndertow(c))) + response.cookies.foreach(c => exchange.setResponseCookie(Cookie.toUndertow(c))) exchange.setStatusCode(response.statusCode) response.data.write(exchange.getOutputStream) diff --git a/cask/src/cask/model/Params.scala b/cask/src/cask/model/Params.scala new file mode 100644 index 0000000..8f206c8 --- /dev/null +++ b/cask/src/cask/model/Params.scala @@ -0,0 +1,99 @@ +package cask.model + +import java.io.InputStream + +import cask.endpoints.ParamReader.NilParam +import io.undertow.server.HttpServerExchange +import io.undertow.server.handlers.CookieImpl + +class Subpath(val value: Seq[String]) +object Subpath{ + implicit object SubpathParam extends NilParam[Subpath]((ctx, label) => new Subpath(ctx.remaining)) +} + +case class Request(exchange: HttpServerExchange){ + import collection.JavaConverters._ + lazy val cookies: Map[String, Cookie] = { + exchange.getRequestCookies.asScala.mapValues(Cookie.fromUndertow).toMap + } + lazy val data: InputStream = exchange.getInputStream + lazy val queryParams: Map[String, Seq[String]] = { + exchange.getQueryParameters.asScala.mapValues(_.asScala.toArray.toSeq).toMap + } + lazy val headers: Map[String, Seq[String]] = { + exchange.getRequestHeaders.asScala + .map{ header => header.getHeaderName.toString.toLowerCase -> header.asScala } + .toMap + } +} +object Request{ + implicit object RequestParam extends NilParam[Request]((ctx, label) => new Request(ctx.exchange)) +} +object Cookie{ + implicit object CookieParam extends NilParam[Cookie]((ctx, label) => + Cookie.fromUndertow(ctx.exchange.getRequestCookies().get(label)) + ) + def fromUndertow(from: io.undertow.server.handlers.Cookie): Cookie = { + Cookie( + from.getName, + from.getValue, + from.getComment, + from.getDomain, + if (from.getExpires == null) null else from.getExpires.toInstant, + from.getMaxAge, + from.getPath, + from.getVersion, + from.isDiscard, + from.isHttpOnly, + from.isSecure + ) + } + def toUndertow(from: Cookie): io.undertow.server.handlers.Cookie = { + val out = new CookieImpl(from.name, from.value) + out.setComment(from.comment) + out.setDomain(from.domain) + out.setExpires(if (from.expires == null) null else java.util.Date.from(from.expires)) + out.setMaxAge(from.maxAge) + out.setPath(from.path) + out.setVersion(from.version) + out.setDiscard(from.discard) + out.setHttpOnly(from.httpOnly) + out.setSecure(from.secure) + } +} +case class Cookie(name: String, + value: String, + comment: String = null, + domain: String = null, + expires: java.time.Instant = null, + maxAge: Integer = null, + path: String = null, + version: Int = 1, + discard: Boolean = false, + httpOnly: Boolean = false, + secure: Boolean = false) { + +} + + +object FormValue{ + 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) + } + 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) + } +} diff --git a/cask/src/cask/model/Response.scala b/cask/src/cask/model/Response.scala index 5443014..3166656 100644 --- a/cask/src/cask/model/Response.scala +++ b/cask/src/cask/model/Response.scala @@ -2,7 +2,7 @@ package cask.model import java.io.{InputStream, OutputStream, OutputStreamWriter} -import cask.endpoints.Cookie +import io.undertow.server.HttpServerExchange trait BaseResponse{ @@ -71,10 +71,7 @@ case class Static(path: String) extends BaseResponse { } -case class Request(cookies: Map[String, Cookie], - data: InputStream, - queryParams: Map[String, Seq[String]], - headers: Map[String, Seq[String]]) + case class Response(data: BaseResponse.Data, statusCode: Int = 200, diff --git a/cask/src/cask/package.scala b/cask/src/cask/package.scala index b715814..791bc51 100644 --- a/cask/src/cask/package.scala +++ b/cask/src/cask/package.scala @@ -6,6 +6,14 @@ 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 Subpath = model.Subpath + val Subpath = model.Subpath + type Request = model.Request + val Request = model.Request // endpoints type get = endpoints.get @@ -16,14 +24,6 @@ package object cask { type postJson = endpoints.postJson type postForm = endpoints.postForm - // endpoints misc - type FormValue = endpoints.FormValue - val FormValue = endpoints.FormValue - type Cookie = endpoints.Cookie - val Cookie = endpoints.Cookie - type Subpath = endpoints.Subpath - val Subpath = endpoints.Subpath - // main type MainRoutes = main.MainRoutes type Routes = main.Routes diff --git a/cask/test/src/test/cask/MinimalApplication.scala b/cask/test/src/test/cask/MinimalApplication.scala index caa6184..4bb1ca1 100644 --- a/cask/test/src/test/cask/MinimalApplication.scala +++ b/cask/test/src/test/cask/MinimalApplication.scala @@ -6,5 +6,12 @@ object MinimalApplication extends cask.MainRoutes{ "Hello World!" } + @cask.get("/request-info") + def hello(request: cask.Request) = { + request.queryParams.toString + "\n" + + request.headers.toString + "\n" + + request.cookies.toString + } + initialize() } -- cgit v1.2.3