Skip to content

Instantly share code, notes, and snippets.

@igstan
Last active August 29, 2015 13:58
Show Gist options
  • Save igstan/10023238 to your computer and use it in GitHub Desktop.
Save igstan/10023238 to your computer and use it in GitHub Desktop.
object Example {
trait HttpParser[A] {
def parse: Option[A]
}
trait HttpRenderer[B] {
def render(b: B): String
}
object HttpRenderer {
implicit val StringRenderer = new HttpRenderer[String] {
override def render(s: String) = s
}
}
// case class HttpResponse[A](
// code: Int,
// body: A,
// renderer: HttpRenderer[A]
// )
abstract class HttpResponse {
type A
val code: Int
val body: A
val renderer: HttpRenderer[A]
}
object Ok {
def apply[B : HttpRenderer](b: B) =
new HttpResponse {
type A = B
val code = 200
val body = b
val renderer = implicitly[HttpRenderer[B]]
}
}
object BadRequest {
def apply[B : HttpRenderer](b: B) =
new HttpResponse {
type A = B
val code = 400
val body = b
val renderer = implicitly[HttpRenderer[B]]
}
}
case class UserRequest(email: String)
object UserRequest {
implicit val UserRequestParser = new HttpParser[UserRequest] {
override def parse: Option[UserRequest] =
// Hardcoding for the sake of example.
Some(UserRequest("some@email.com"))
}
}
case class UserResponse(email: String)
object UserResponse {
implicit val UserResponseRenderer = new HttpRenderer[UserResponse] {
override def render(user: UserResponse): String = s"User[email = ${user.email}]"
}
}
def parse[A: HttpParser](fn: A => HttpResponse): HttpResponse = {
implicitly[HttpParser[A]].parse match {
case Some(a) => fn(a)
case None => BadRequest("Cannot parse body.")
}
}
def exampleUsage =
parse[UserRequest] { user =>
if (user.email != "some@email.com") {
BadRequest("Invalid user email")
} else {
Ok(UserResponse(email=user.email))
}
}
def main(args: Array[String]): Unit = {
val e = exampleUsage
println(e.renderer.render(e.body))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment