Skip to content

Instantly share code, notes, and snippets.

@dakatsuka
Last active November 7, 2015 15:09
Show Gist options
  • Save dakatsuka/36aa89291a4b00d8d09f to your computer and use it in GitHub Desktop.
Save dakatsuka/36aa89291a4b00d8d09f to your computer and use it in GitHub Desktop.
http4sお試し
name := "http4stest"
version := "0.1.0"
scalaVersion := "2.11.7"
resolvers += "Scalaz Bintray Repo" at "http://dl.bintray.com/scalaz/releases"
libraryDependencies ++= Seq(
"org.http4s" %% "http4s-dsl" % "0.10.1",
"org.http4s" %% "http4s-blaze-server" % "0.10.1",
"org.http4s" %% "http4s-blaze-client" % "0.10.1",
"org.http4s" %% "http4s-argonaut" % "0.10.1",
"com.github.mauricio" %% "mysql-async" % "0.2.18"
)
package jp.dakatsuka.http4s
import argonaut.Argonaut._
import argonaut.CodecJson
import com.github.mauricio.async.db.{RowData, Configuration}
import com.github.mauricio.async.db.mysql.MySQLConnection
import org.http4s.argonaut._
import org.http4s.EntityEncoder
import org.http4s.dsl._
import org.http4s.server.HttpService
import org.http4s.server.blaze.BlazeBuilder
import scala.concurrent.duration._
import scala.concurrent.{Await, Future}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{Success, Failure}
import scalaz.concurrent.Task
import scalaz.syntax.either._
case class User(id: Long, email: String, screen_name: String)
object User {
implicit val userCodec: CodecJson[User] = casecodec3(User.apply, User.unapply)("id", "email", "screen_name")
implicit val userEncoder: EntityEncoder[User] = jsonEncoderOf[User]
implicit val usersEncoder: EntityEncoder[Seq[User]] = jsonEncoderOf[Seq[User]]
val selectAll = "SELECT * FROM users"
val selectOne = "SELECT * FROM users WHERE id = ? LIMIT 1"
def all(implicit connection: MySQLConnection): Future[Seq[User]] =
connection.sendQuery(selectAll).map { _.rows.map(rs =>
rs.map(toEntity).toSeq
).getOrElse(Seq.empty)}
def find(id: Long)(implicit connection: MySQLConnection): Future[Option[User]] =
connection.sendPreparedStatement(selectOne, Seq(id)).map { _.rows.flatMap(rs => rs.headOption.map(toEntity)) }
private def toEntity(row: RowData): User = User(
id = row("id").asInstanceOf[Int].toLong,
email = row("email").asInstanceOf[String],
screen_name = row("screen_name").asInstanceOf[String]
)
}
object MainService {
implicit class FutureToTaskTransformer[+A](future: Future[A]) {
def toTask: Task[A] = {
Task.async { register =>
future.onComplete {
case Success(v) => register(v.right)
case Failure(e) => register(e.left)
}
}
}
}
val configuration = Configuration(username = "root", host = "127.0.0.1", database = Some("testdb"), port = 3306)
implicit val connection = new MySQLConnection(configuration)
val service = HttpService {
case GET -> Root =>
Ok("Document Root")
case GET -> Root / "users" =>
User.all.toTask.flatMap(users => Ok(users))
case GET -> Root / "users" / LongVar(id) =>
User.find(id).toTask.flatMap {
case Some(user) => Ok(user)
case _ => NotFound()
}
}
def main(args: Array[String]): Unit = {
Await.result(connection.connect, 5 seconds)
BlazeBuilder.bindHttp(8080)
.mountService(service)
.run
.awaitShutdown()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment