diff --git a/core/src/main/scala/org/http4s/rho/PathBuilder.scala b/core/src/main/scala/org/http4s/rho/PathBuilder.scala index 5328fb5d..4f83f2f9 100644 --- a/core/src/main/scala/org/http4s/rho/PathBuilder.scala +++ b/core/src/main/scala/org/http4s/rho/PathBuilder.scala @@ -18,13 +18,12 @@ import scala.reflect.runtime.universe.TypeTag /** Fully functional path building */ final class PathBuilder[T <: HList](val method: Method, val path: PathRule) - extends HeaderAppendable[T] - with RouteExecutable[T] + extends RouteExecutable[T] with Decodable[T, Nothing] with UriConvertible - with Validatable[T] + with HeaderAppendable[T] { - type Self = PathBuilder[T] + type HeaderAppendResult[T <: HList] = Router[T] override def headers: HeaderRule = EmptyHeaderRule @@ -51,9 +50,9 @@ final class PathBuilder[T <: HList](val method: Method, val path: PathRule) def /[T2 <: HList](t: RequestLineBuilder[T2])(implicit prep: Prepend[T2, T]): QueryBuilder[prep.Out] = QueryBuilder(method, PathAnd(path, t.path), t.query) - def toAction: Router[T] = validate(TypedHeader[HNil](EmptyHeaderRule)) + def toAction: Router[T] = >>>(TypedHeader[HNil](EmptyHeaderRule)) - override def validate[T1 <: HList](h2: TypedHeader[T1])(implicit prep: Prepend[T1, T]): Router[prep.Out] = + override def >>>[T1 <: HList](h2: TypedHeader[T1])(implicit prep: Prepend[T1, T]): Router[prep.Out] = Router(method, path, EmptyQuery, h2.rule) override def decoding[R](decoder: EntityDecoder[R]): CodecRouter[T, R] = CodecRouter(toAction, decoder) diff --git a/core/src/main/scala/org/http4s/rho/QueryBuilder.scala b/core/src/main/scala/org/http4s/rho/QueryBuilder.scala index 986af20e..3d909439 100644 --- a/core/src/main/scala/org/http4s/rho/QueryBuilder.scala +++ b/core/src/main/scala/org/http4s/rho/QueryBuilder.scala @@ -10,12 +10,13 @@ import shapeless.ops.hlist.Prepend import shapeless.{ ::, HList } case class QueryBuilder[T <: HList](method: Method, - path: PathRule, - query: QueryRule) + path: PathRule, + query: QueryRule) extends RouteExecutable[T] with HeaderAppendable[T] - with UriConvertible { - override type Self = QueryBuilder[T] + with UriConvertible +{ + override type HeaderAppendResult[T <: HList] = Router[T] override def makeAction[F](f: F, hf: HListToFunc[T, F]): RhoAction[T, F] = RhoAction(Router(method, path, query, headers), f, hf) diff --git a/core/src/main/scala/org/http4s/rho/Router.scala b/core/src/main/scala/org/http4s/rho/Router.scala index f75986fe..e4e30731 100644 --- a/core/src/main/scala/org/http4s/rho/Router.scala +++ b/core/src/main/scala/org/http4s/rho/Router.scala @@ -32,8 +32,7 @@ case class Router[T <: HList](method: Method, with RoutingEntity[T] with Decodable[T, Nothing] { - - type Self = Router[T] + override type HeaderAppendResult[T <: HList] = Router[T] override def >>>[T2 <: HList](v: TypedHeader[T2])(implicit prep1: Prepend[T2, T]): Router[prep1.Out] = Router(method, path, query, HeaderAnd(headers, v.rule)) @@ -50,11 +49,14 @@ case class CodecRouter[T <: HList, R](router: Router[T], decoder: EntityDecoder[ with RoutingEntity[R::T] with Decodable[T, R] { - type Self = CodecRouter[T, R] + override type HeaderAppendResult[T <: HList] = CodecRouter[T, R] override def >>>[T2 <: HList](v: TypedHeader[T2])(implicit prep1: Prepend[T2, T]): CodecRouter[prep1.Out,R] = CodecRouter(router >>> v, decoder) + /** Append the header to the builder, generating a new typed representation of the route */ +// override def >>>[T2 <: HList](header: TypedHeader[T2])(implicit prep: Prepend[T2, T]): CodecRouter[prep.Out, R] = ??? + override def makeAction[F](f: F, hf: HListToFunc[R::T, F]): RhoAction[R::T, F] = new RhoAction(this, f, hf) diff --git a/core/src/main/scala/org/http4s/rho/Validatable.scala b/core/src/main/scala/org/http4s/rho/Validatable.scala deleted file mode 100644 index a8a5fc92..00000000 --- a/core/src/main/scala/org/http4s/rho/Validatable.scala +++ /dev/null @@ -1,16 +0,0 @@ -package org.http4s.rho - -import bits.HeaderAST._ - -import shapeless.HList -import shapeless.ops.hlist.Prepend - -trait Validatable[T <: HList] { - - /** Checks that specific requirements of a HTTP request header are met */ - def validate[T1 <: HList](header: TypedHeader[T1])(implicit prep: Prepend[T1, T]): Router[prep.Out] - - /** Alias for validate */ - final def >>>[T1 <: HList](header: TypedHeader[T1])(implicit prep: Prepend[T1, T]): Router[prep.Out] = - validate(header) -} diff --git a/core/src/main/scala/org/http4s/rho/bits/HeaderAppendable.scala b/core/src/main/scala/org/http4s/rho/bits/HeaderAppendable.scala index a8b2b061..a071a1d7 100644 --- a/core/src/main/scala/org/http4s/rho/bits/HeaderAppendable.scala +++ b/core/src/main/scala/org/http4s/rho/bits/HeaderAppendable.scala @@ -1,6 +1,8 @@ package org.http4s package rho.bits +import scala.language.higherKinds + import org.http4s.rho.bits.HeaderAST.TypedHeader import shapeless.HList import shapeless.ops.hlist.Prepend @@ -9,8 +11,11 @@ import shapeless.ops.hlist.Prepend * @tparam T1 HList representation of the values to be extracted from the [[Request]] */ trait HeaderAppendable[T1 <: HList] { - type Self <: HeaderAppendable[T1] + type HeaderAppendResult[T <: HList] <: HeaderAppendable[T] /** Append the header to the builder, generating a new typed representation of the route */ - def >>>[T2 <: HList](header: TypedHeader[T2])(implicit prep: Prepend[T2, T1]): HeaderAppendable[prep.Out] + def >>>[T2 <: HList](header: TypedHeader[T2])(implicit prep: Prepend[T2, T1]): HeaderAppendResult[prep.Out] + + final def validate[T2 <: HList](header: TypedHeader[T2])(implicit prep: Prepend[T2, T1]): HeaderAppendResult[prep.Out] = + >>>(header)(prep) } \ No newline at end of file