diff options
Diffstat (limited to 'cask/src')
-rw-r--r-- | cask/src/cask/decorators/compress.scala | 4 | ||||
-rw-r--r-- | cask/src/cask/endpoints/FormEndpoint.scala | 18 | ||||
-rw-r--r-- | cask/src/cask/endpoints/JsonEndpoint.scala | 10 | ||||
-rw-r--r-- | cask/src/cask/endpoints/ParamReader.scala | 16 | ||||
-rw-r--r-- | cask/src/cask/endpoints/StaticEndpoints.scala | 10 | ||||
-rw-r--r-- | cask/src/cask/endpoints/WebEndpoints.scala | 16 | ||||
-rw-r--r-- | cask/src/cask/endpoints/WebSocketEndpoint.scala | 15 | ||||
-rw-r--r-- | cask/src/cask/internal/DispatchTrie.scala | 13 | ||||
-rw-r--r-- | cask/src/cask/main/Decorators.scala | 10 | ||||
-rw-r--r-- | cask/src/cask/main/Main.scala | 4 | ||||
-rw-r--r-- | cask/src/cask/main/Routes.scala | 4 | ||||
-rw-r--r-- | cask/src/cask/model/ParamContext.scala | 5 | ||||
-rw-r--r-- | cask/src/cask/model/Params.scala | 16 | ||||
-rw-r--r-- | cask/src/cask/model/Response.scala | 98 | ||||
-rw-r--r-- | cask/src/cask/package.scala | 8 |
15 files changed, 105 insertions, 142 deletions
diff --git a/cask/src/cask/decorators/compress.scala b/cask/src/cask/decorators/compress.scala index 22bd29e..75e2bed 100644 --- a/cask/src/cask/decorators/compress.scala +++ b/cask/src/cask/decorators/compress.scala @@ -3,11 +3,11 @@ import java.io.{ByteArrayOutputStream, OutputStream} import java.util.zip.{DeflaterOutputStream, GZIPOutputStream} import cask.internal.Router -import cask.model.{ParamContext, Response} +import cask.model.{Request, Response} import collection.JavaConverters._ class compress extends cask.Decorator{ - def wrapFunction(ctx: ParamContext, delegate: Delegate) = { + def wrapFunction(ctx: Request, delegate: Delegate) = { val acceptEncodings = ctx.exchange.getRequestHeaders.get("Accept-Encoding").asScala.flatMap(_.split(", ")) delegate(Map()).map{ v => val (newData, newHeaders) = if (acceptEncodings.exists(_.toLowerCase == "gzip")) { diff --git a/cask/src/cask/endpoints/FormEndpoint.scala b/cask/src/cask/endpoints/FormEndpoint.scala index a952a2a..cc74093 100644 --- a/cask/src/cask/endpoints/FormEndpoint.scala +++ b/cask/src/cask/endpoints/FormEndpoint.scala @@ -7,40 +7,40 @@ import io.undertow.server.handlers.form.FormParserFactory import collection.JavaConverters._ -sealed trait FormReader[T] extends Router.ArgReader[Seq[FormEntry], T, ParamContext] +sealed trait FormReader[T] extends Router.ArgReader[Seq[FormEntry], T, Request] object FormReader{ implicit def paramFormReader[T: QueryParamReader] = new FormReader[T]{ def arity = implicitly[QueryParamReader[T]].arity - def read(ctx: ParamContext, label: String, input: Seq[FormEntry]) = { + def read(ctx: Request, 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 + def read(ctx: Request, 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 + def read(ctx: Request, label: String, input: Seq[FormEntry]) = input } implicit def formValueReader = new FormReader[FormValue]{ def arity = 1 - def read(ctx: ParamContext, label: String, input: Seq[FormEntry]) = input.head.asInstanceOf[FormValue] + def read(ctx: Request, 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[FormEntry]) = input.map(_.asInstanceOf[FormValue]) + def read(ctx: Request, label: String, input: Seq[FormEntry]) = input.map(_.asInstanceOf[FormValue]) } implicit def formFileReader = new FormReader[FormFile]{ def arity = 1 - def read(ctx: ParamContext, label: String, input: Seq[FormEntry]) = input.head.asInstanceOf[FormFile] + def read(ctx: Request, label: String, input: Seq[FormEntry]) = input.head.asInstanceOf[FormFile] } implicit def formFilesReader = new FormReader[Seq[FormFile]]{ def arity = 1 - def read(ctx: ParamContext, label: String, input: Seq[FormEntry]) = input.map(_.asInstanceOf[FormFile]) + def read(ctx: Request, label: String, input: Seq[FormEntry]) = input.map(_.asInstanceOf[FormFile]) } } class postForm(val path: String, override val subpath: Boolean = false) extends Endpoint { @@ -49,7 +49,7 @@ class postForm(val path: String, override val subpath: Boolean = false) extends val methods = Seq("post") type Input = Seq[FormEntry] type InputParser[T] = FormReader[T] - def wrapFunction(ctx: ParamContext, + def wrapFunction(ctx: Request, delegate: Map[String, Input] => Router.Result[Output]): Router.Result[Response] = { try { val formData = FormParserFactory.builder().build().createParser(ctx.exchange).parseBlocking() diff --git a/cask/src/cask/endpoints/JsonEndpoint.scala b/cask/src/cask/endpoints/JsonEndpoint.scala index f91b888..212597c 100644 --- a/cask/src/cask/endpoints/JsonEndpoint.scala +++ b/cask/src/cask/endpoints/JsonEndpoint.scala @@ -5,15 +5,15 @@ import java.io.ByteArrayOutputStream import cask.internal.{Router, Util} import cask.internal.Router.EntryPoint import cask.main.{Endpoint, HttpDecorator, Routes} -import cask.model.{ParamContext, Response} +import cask.model.{Request, Response} -sealed trait JsReader[T] extends Router.ArgReader[ujson.Js.Value, T, cask.model.ParamContext] +sealed trait JsReader[T] extends Router.ArgReader[ujson.Js.Value, T, cask.model.Request] object JsReader{ implicit def defaultJsReader[T: upickle.default.Reader] = new JsReader[T]{ def arity = 1 - def read(ctx: cask.model.ParamContext, label: String, input: ujson.Js.Value): T = { + def read(ctx: cask.model.Request, label: String, input: ujson.Js.Value): T = { implicitly[upickle.default.Reader[T]].apply(input) } } @@ -21,7 +21,7 @@ object JsReader{ implicit def paramReader[T: ParamReader] = new JsReader[T] { override def arity = 0 - override def read(ctx: cask.model.ParamContext, label: String, v: ujson.Js.Value) = { + override def read(ctx: cask.model.Request, label: String, v: ujson.Js.Value) = { implicitly[ParamReader[T]].read(ctx, label, Nil) } } @@ -31,7 +31,7 @@ class postJson(val path: String, override val subpath: Boolean = false) extends val methods = Seq("post") type Input = ujson.Js.Value type InputParser[T] = JsReader[T] - def wrapFunction(ctx: ParamContext, + def wrapFunction(ctx: Request, delegate: Map[String, Input] => Router.Result[Output]): Router.Result[Response] = { val obj = for{ str <- diff --git a/cask/src/cask/endpoints/ParamReader.scala b/cask/src/cask/endpoints/ParamReader.scala index f1ec0bf..e43f482 100644 --- a/cask/src/cask/endpoints/ParamReader.scala +++ b/cask/src/cask/endpoints/ParamReader.scala @@ -1,22 +1,28 @@ package cask.endpoints import cask.internal.Router -import cask.model.ParamContext +import cask.model.{Cookie, Request} import io.undertow.server.HttpServerExchange import io.undertow.server.handlers.form.{FormData, FormParserFactory} -abstract class ParamReader[T] extends Router.ArgReader[Unit, T, cask.model.ParamContext]{ +abstract class ParamReader[T] extends Router.ArgReader[Unit, T, cask.model.Request]{ def arity: Int - def read(ctx: cask.model.ParamContext, label: String, v: Unit): T + def read(ctx: cask.model.Request, label: String, v: Unit): T } object ParamReader{ - class NilParam[T](f: (ParamContext, String) => T) extends ParamReader[T]{ + class NilParam[T](f: (Request, String) => T) extends ParamReader[T]{ def arity = 0 - def read(ctx: cask.model.ParamContext, label: String, v: Unit): T = f(ctx, label) + def read(ctx: cask.model.Request, label: String, v: Unit): T = f(ctx, label) } implicit object HttpExchangeParam extends NilParam[HttpServerExchange]((ctx, label) => ctx.exchange) implicit object FormDataParam extends NilParam[FormData]((ctx, label) => FormParserFactory.builder().build().createParser(ctx.exchange).parseBlocking() ) + + implicit object RequestParam extends NilParam[Request]((ctx, label) => ctx) + + implicit object CookieParam extends NilParam[Cookie]((ctx, label) => + Cookie.fromUndertow(ctx.exchange.getRequestCookies().get(label)) + ) } diff --git a/cask/src/cask/endpoints/StaticEndpoints.scala b/cask/src/cask/endpoints/StaticEndpoints.scala index 1d66b2c..15eae0d 100644 --- a/cask/src/cask/endpoints/StaticEndpoints.scala +++ b/cask/src/cask/endpoints/StaticEndpoints.scala @@ -1,7 +1,7 @@ package cask.endpoints import cask.main.Endpoint -import cask.model.ParamContext +import cask.model.Request class staticFiles(val path: String) extends Endpoint{ type Output = String @@ -9,8 +9,8 @@ class staticFiles(val path: String) extends Endpoint{ type Input = Seq[String] type InputParser[T] = QueryParamReader[T] override def subpath = true - def wrapFunction(ctx: ParamContext, delegate: Delegate): Returned = { - delegate(Map()).map(t => cask.model.StaticFile(t + "/" + ctx.remaining.mkString("/"))) + def wrapFunction(ctx: Request, delegate: Delegate): Returned = { + delegate(Map()).map(t => cask.model.StaticFile(t + "/" + ctx.remainingPathSegments.mkString("/"))) } def wrapPathSegment(s: String): Input = Seq(s) @@ -22,9 +22,9 @@ class staticResources(val path: String, resourceRoot: ClassLoader = getClass.get type Input = Seq[String] type InputParser[T] = QueryParamReader[T] override def subpath = true - def wrapFunction(ctx: ParamContext, delegate: Delegate): Returned = { + def wrapFunction(ctx: Request, delegate: Delegate): Returned = { delegate(Map()).map(t => - cask.model.StaticResource(t + "/" + ctx.remaining.mkString("/"), resourceRoot) + cask.model.StaticResource(t + "/" + ctx.remainingPathSegments.mkString("/"), resourceRoot) ) } diff --git a/cask/src/cask/endpoints/WebEndpoints.scala b/cask/src/cask/endpoints/WebEndpoints.scala index 41c3113..02aeec4 100644 --- a/cask/src/cask/endpoints/WebEndpoints.scala +++ b/cask/src/cask/endpoints/WebEndpoints.scala @@ -2,7 +2,7 @@ package cask.endpoints import cask.internal.Router import cask.main.{Endpoint, HttpDecorator} -import cask.model.{ParamContext, Response} +import cask.model.{Request, Response} import collection.JavaConverters._ @@ -11,7 +11,7 @@ trait WebEndpoint extends Endpoint with HttpDecorator{ type Output = Response type Input = Seq[String] type InputParser[T] = QueryParamReader[T] - def wrapFunction(ctx: ParamContext, + def wrapFunction(ctx: Request, delegate: Map[String, Input] => Router.Result[Output]): Router.Result[Response] = { delegate( ctx.exchange.getQueryParameters @@ -34,14 +34,14 @@ class put(val path: String, override val subpath: Boolean = false) extends WebEn class route(val path: String, val methods: Seq[String], override val subpath: Boolean = false) extends WebEndpoint abstract class QueryParamReader[T] - extends Router.ArgReader[Seq[String], T, cask.model.ParamContext]{ + extends Router.ArgReader[Seq[String], T, cask.model.Request]{ def arity: Int - def read(ctx: cask.model.ParamContext, label: String, v: Seq[String]): T + def read(ctx: cask.model.Request, label: String, v: Seq[String]): T } object QueryParamReader{ class SimpleParam[T](f: String => T) extends QueryParamReader[T]{ def arity = 1 - def read(ctx: cask.model.ParamContext, label: String, v: Seq[String]): T = f(v.head) + def read(ctx: cask.model.Request, label: String, v: Seq[String]): T = f(v.head) } implicit object StringParam extends SimpleParam[String](x => x) @@ -54,20 +54,20 @@ object QueryParamReader{ implicit object FloatParam extends SimpleParam[Float](_.toFloat) implicit def SeqParam[T: QueryParamReader] = new QueryParamReader[Seq[T]]{ def arity = 1 - def read(ctx: cask.model.ParamContext, label: String, v: Seq[String]): Seq[T] = { + def read(ctx: cask.model.Request, label: String, v: Seq[String]): Seq[T] = { v.map(x => implicitly[QueryParamReader[T]].read(ctx, label, Seq(x))) } } implicit def OptionParam[T: QueryParamReader] = new QueryParamReader[Option[T]]{ def arity = 1 - def read(ctx: cask.model.ParamContext, label: String, v: Seq[String]): Option[T] = { + def read(ctx: cask.model.Request, label: String, v: Seq[String]): Option[T] = { v.headOption.map(x => implicitly[QueryParamReader[T]].read(ctx, label, Seq(x))) } } implicit def paramReader[T: ParamReader] = new QueryParamReader[T] { override def arity = 0 - override def read(ctx: cask.model.ParamContext, label: String, v: Seq[String]) = { + override def read(ctx: cask.model.Request, label: String, v: Seq[String]) = { implicitly[ParamReader[T]].read(ctx, label, v) } } diff --git a/cask/src/cask/endpoints/WebSocketEndpoint.scala b/cask/src/cask/endpoints/WebSocketEndpoint.scala index 89c05b9..8c6bc16 100644 --- a/cask/src/cask/endpoints/WebSocketEndpoint.scala +++ b/cask/src/cask/endpoints/WebSocketEndpoint.scala @@ -1,25 +1,22 @@ package cask.endpoints import cask.internal.Router -import cask.model.{ParamContext, Subpath} +import cask.model.Request import io.undertow.server.HttpServerExchange import io.undertow.websockets.WebSocketConnectionCallback -trait WebsocketParam[T] extends Router.ArgReader[Seq[String], T, cask.model.ParamContext] +trait WebsocketParam[T] extends Router.ArgReader[Seq[String], T, cask.model.Request] object WebsocketParam{ - class NilParam[T](f: (ParamContext, String) => T) extends WebsocketParam[T]{ + class NilParam[T](f: (Request, String) => T) extends WebsocketParam[T]{ def arity = 0 - def read(ctx: ParamContext, label: String, v: Seq[String]): T = f(ctx, label) + def read(ctx: Request, label: String, v: Seq[String]): T = f(ctx, label) } implicit object HttpExchangeParam extends NilParam[HttpServerExchange]( (ctx, label) => ctx.exchange ) - implicit object SubpathParam extends NilParam[Subpath]( - (ctx, label) => new Subpath(ctx.remaining) - ) class SimpleParam[T](f: String => T) extends WebsocketParam[T]{ def arity = 1 - def read(ctx: cask.model.ParamContext, label: String, v: Seq[String]): T = f(v.head) + def read(ctx: cask.model.Request, label: String, v: Seq[String]): T = f(v.head) } implicit object StringParam extends SimpleParam[String](x => x) @@ -44,7 +41,7 @@ class websocket(val path: String, override val subpath: Boolean = false) extends type Input = Seq[String] type InputParser[T] = WebsocketParam[T] type Returned = Router.Result[WebsocketResult] - def wrapFunction(ctx: ParamContext, delegate: Delegate): Returned = delegate(Map()) + def wrapFunction(ctx: Request, delegate: Delegate): Returned = delegate(Map()) def wrapPathSegment(s: String): Input = Seq(s) diff --git a/cask/src/cask/internal/DispatchTrie.scala b/cask/src/cask/internal/DispatchTrie.scala index 57d8d9d..952c39b 100644 --- a/cask/src/cask/internal/DispatchTrie.scala +++ b/cask/src/cask/internal/DispatchTrie.scala @@ -36,15 +36,20 @@ object DispatchTrie{ }else{ DispatchTrie[T]( current = terminals.headOption.map(x => x._2 -> x._3), - children = continuations.map{ case (k, vs) => - if (!k.startsWith("::")) (k, construct(index + 1, vs)) - else (k, DispatchTrie(Some(vs.head._2 -> vs.head._3), Map())) - }.toMap + children = continuations.map{ case (k, vs) => (k, construct(index + 1, vs))}.toMap ) } } } +/** + * A simple Trie that can be compiled from a list of endpoints, to allow + * endpoint lookup in O(length-of-request-path) time. Lookup returns the + * [[T]] this trie contains, as well as a map of bound wildcards (path + * segments starting with `:`) and any remaining un-used path segments + * (only when `current._2 == true`, indicating this route allows trailing + * segments) + */ case class DispatchTrie[T](current: Option[(T, Boolean)], children: Map[String, DispatchTrie[T]]){ final def lookup(remainingInput: List[String], diff --git a/cask/src/cask/main/Decorators.scala b/cask/src/cask/main/Decorators.scala index 239cab4..0515232 100644 --- a/cask/src/cask/main/Decorators.scala +++ b/cask/src/cask/main/Decorators.scala @@ -2,7 +2,7 @@ package cask.main import cask.internal.Router import cask.internal.Router.ArgReader -import cask.model.{ParamContext, Response} +import cask.model.{Request, Response} trait Endpoint extends BaseEndpoint with HttpDecorator @@ -44,11 +44,11 @@ trait BaseEndpoint extends BaseDecorator{ trait BaseDecorator{ type Input - type InputParser[T] <: ArgReader[Input, T, ParamContext] + type InputParser[T] <: ArgReader[Input, T, Request] type Output type Delegate = Map[String, Input] => Router.Result[Output] type Returned <: Router.Result[Any] - def wrapFunction(ctx: ParamContext, delegate: Delegate): Returned + def wrapFunction(ctx: Request, delegate: Delegate): Returned def getParamParser[T](implicit p: InputParser[T]) = p } trait HttpDecorator extends BaseDecorator{ @@ -73,10 +73,10 @@ trait Decorator extends HttpDecorator { type InputParser[T] = NoOpParser[Input, T] } -class NoOpParser[Input, T] extends ArgReader[Input, T, ParamContext] { +class NoOpParser[Input, T] extends ArgReader[Input, T, Request] { def arity = 1 - def read(ctx: ParamContext, label: String, input: Input) = input.asInstanceOf[T] + def read(ctx: Request, label: String, input: Input) = input.asInstanceOf[T] } object NoOpParser{ implicit def instance[Input, T] = new NoOpParser[Input, T] diff --git a/cask/src/cask/main/Main.scala b/cask/src/cask/main/Main.scala index 70fe206..46e1a65 100644 --- a/cask/src/cask/main/Main.scala +++ b/cask/src/cask/main/Main.scala @@ -74,7 +74,7 @@ abstract class BaseMain{ case None => writeResponse(exchange, handleNotFound()) case Some(((routes, metadata), extBindings, remaining)) => - val ctx = ParamContext(exchange, remaining) + val ctx = Request(exchange, remaining) def rec(remaining: List[Decorator], bindings: List[Map[String, Any]]): Router.Result[Any] = try { remaining match { @@ -84,7 +84,7 @@ abstract class BaseMain{ case Nil => metadata.endpoint.wrapFunction(ctx, epBindings => metadata.entryPoint - .asInstanceOf[EntryPoint[cask.main.Routes, cask.model.ParamContext]] + .asInstanceOf[EntryPoint[cask.main.Routes, cask.model.Request]] .invoke(routes, ctx, (epBindings ++ extBindings.mapValues(metadata.endpoint.wrapPathSegment)) :: bindings.reverse) .asInstanceOf[Router.Result[Nothing]] ) diff --git a/cask/src/cask/main/Routes.scala b/cask/src/cask/main/Routes.scala index aaec832..1a74b87 100644 --- a/cask/src/cask/main/Routes.scala +++ b/cask/src/cask/main/Routes.scala @@ -1,7 +1,7 @@ package cask.main import cask.internal.Router.EntryPoint -import cask.model.ParamContext +import cask.model.Request import scala.reflect.macros.blackbox.Context import language.experimental.macros @@ -43,7 +43,7 @@ object Routes{ m.asInstanceOf[MethodSymbol], weakTypeOf[T], q"${annotObjectSyms.head}.convertToResultType", - tq"cask.ParamContext", + tq"cask.Request", annotObjectSyms.map(annotObjectSym => q"$annotObjectSym.getParamParser"), annotObjectSyms.map(annotObjectSym => tq"$annotObjectSym.Input") diff --git a/cask/src/cask/model/ParamContext.scala b/cask/src/cask/model/ParamContext.scala deleted file mode 100644 index 43da260..0000000 --- a/cask/src/cask/model/ParamContext.scala +++ /dev/null @@ -1,5 +0,0 @@ -package cask.model - -import io.undertow.server.HttpServerExchange - -case class ParamContext(exchange: HttpServerExchange, remaining: Seq[String]) diff --git a/cask/src/cask/model/Params.scala b/cask/src/cask/model/Params.scala index bd10161..270c190 100644 --- a/cask/src/cask/model/Params.scala +++ b/cask/src/cask/model/Params.scala @@ -2,18 +2,11 @@ package cask.model import java.io.{ByteArrayOutputStream, InputStream} -import cask.endpoints.ParamReader.NilParam import cask.internal.Util import io.undertow.server.HttpServerExchange import io.undertow.server.handlers.CookieImpl -import io.undertow.websockets.spi.WebSocketHttpExchange -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){ +case class Request(exchange: HttpServerExchange, remainingPathSegments: Seq[String]){ import collection.JavaConverters._ lazy val cookies: Map[String, Cookie] = { exchange.getRequestCookies.asScala.mapValues(Cookie.fromUndertow).toMap @@ -33,13 +26,8 @@ case class Request(exchange: HttpServerExchange){ .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, diff --git a/cask/src/cask/model/Response.scala b/cask/src/cask/model/Response.scala index 9ac5664..59b44c9 100644 --- a/cask/src/cask/model/Response.scala +++ b/cask/src/cask/model/Response.scala @@ -4,22 +4,24 @@ import java.io.{InputStream, OutputStream, OutputStreamWriter} import cask.internal.Util - -trait Response{ - def data: Response.Data - def statusCode: Int - def headers: Seq[(String, String)] - def cookies: Seq[Cookie] -} +/** + * The basic response returned by a HTTP endpoint. + * + * Note that [[data]] by default can take in a wide range of types: strings, + * bytes, uPickle JSON-convertable types or arbitrary input streams. You can + * also construct your own implementations of `Response.Data`. + */ +case class Response( + data: Response.Data, + statusCode: Int, + headers: Seq[(String, String)], + cookies: Seq[Cookie] +) object Response{ def apply(data: Data, statusCode: Int = 200, headers: Seq[(String, String)] = Nil, - cookies: Seq[Cookie] = Nil) = Simple(data, statusCode, headers, cookies) - case class Simple(data: Data, - statusCode: Int = 200, - headers: Seq[(String, String)] = Nil, - cookies: Seq[Cookie] = Nil) extends Response + cookies: Seq[Cookie] = Nil) = new Response(data, statusCode, headers, cookies) implicit def dataResponse[T](t: T)(implicit c: T => Data) = Response(t) trait Data{ @@ -43,59 +45,33 @@ object Response{ } } } -case class Redirect(url: String) extends Response{ - override def data = "" - - override def statusCode = 301 - - override def headers = Seq("Location" -> url) - - override def cookies = Nil +object Redirect{ + def apply(url: String) = Response("", 301, Seq("Location" -> url), Nil) } -case class Abort(code: Int) extends Response { - override def data = "" - - override def statusCode = code - - override def headers = Nil - - override def cookies = Nil +object Abort{ + def apply(code: Int) = Response("", code, Nil, Nil) } - -case class StaticFile(path: String) extends Response { - val relPath = java.nio.file.Paths.get(path) - val (data0, statusCode0) = - if (java.nio.file.Files.exists(relPath) && java.nio.file.Files.isRegularFile(relPath)){ - (java.nio.file.Files.newInputStream(relPath): Response.Data, 200) - }else{ - ("": Response.Data, 404) - } - override def data = data0 - - override def statusCode = statusCode0 - - override def headers = Nil - - override def cookies = Nil +object StaticFile{ + def apply(path: String) = { + val relPath = java.nio.file.Paths.get(path) + val (data0, statusCode0) = + if (java.nio.file.Files.exists(relPath) && java.nio.file.Files.isRegularFile(relPath)){ + (java.nio.file.Files.newInputStream(relPath): Response.Data, 200) + }else{ + ("": Response.Data, 404) + } + Response(data0, statusCode0, Nil, Nil) + } } - -case class StaticResource(path: String, resourceRoot: ClassLoader) extends Response { - val relPath = java.nio.file.Paths.get(path) - val (data0, statusCode0) = resourceRoot.getResourceAsStream(path) match{ - case null => ("": Response.Data, 404) - case res => (res: Response.Data, 200) +object StaticResource{ + def apply(path: String, resourceRoot: ClassLoader) = { + val relPath = java.nio.file.Paths.get(path) + val (data0, statusCode0) = resourceRoot.getResourceAsStream(path) match{ + case null => ("": Response.Data, 404) + case res => (res: Response.Data, 200) + } + Response(data0, statusCode0, Nil, Nil) } - - override def data = data0 - - override def statusCode = statusCode0 - - override def headers = Nil - - override def cookies = Nil } - - - diff --git a/cask/src/cask/package.scala b/cask/src/cask/package.scala index 06d9738..cd1a8e5 100644 --- a/cask/src/cask/package.scala +++ b/cask/src/cask/package.scala @@ -2,10 +2,10 @@ package object cask { // model type Response = model.Response val Response = model.Response - type Abort = model.Abort val Abort = model.Abort - type Redirect = model.Redirect val Redirect = model.Redirect + val StaticFile = model.StaticFile + val StaticResource = model.StaticResource type FormEntry = model.FormEntry val FormEntry = model.FormEntry type FormValue = model.FormValue @@ -14,12 +14,8 @@ package object cask { val FormFile = model.FormFile type Cookie = model.Cookie val Cookie = model.Cookie - type Subpath = model.Subpath - val Subpath = model.Subpath type Request = model.Request val Request = model.Request - type ParamContext = model.ParamContext - val ParamContext = model.ParamContext // endpoints type websocket = endpoints.websocket |