🥰

http4s の最小構成:サーバー

2022/10/15に公開

scala-cli の場合

Server.scala
// 非同期ランタイム
//> using lib "org.typelevel::cats-effect:3.4.5"
// http 関係
// http の基本型など
//> using lib "org.http4s::http4s-core:1.0.0-M38"
// ルーティング DSL など
//> using lib "org.http4s::http4s-dsl:1.0.0-M38"
// http サーバー
//> using lib "org.http4s::http4s-ember-server:1.0.0-M38"

import cats.effect._

import org.http4s.HttpRoutes
// Request => F[Response] を表現する型
import com.comcast.ip4s._ 
// ipv4"0.0.0.0", port"8080" などを書けるようにする(不正な値はコンパイルエラー.)
import org.http4s.dsl.io._ 
// case GET -> Root / "echo" / arg => などを書けるようにする
import org.http4s.implicits._
import org.http4s.ember.server._

object Main extends IOApp {

    val echo = HttpRoutes.of[IO] {
        case GET -> Root / "echo" / arg => Ok(arg)
    }.orNotFound
    def run(args: List[String]):IO[ExitCode] = EmberServerBuilder
      .default[IO] // EmberServerBuilder[cats.effect.IO]
      .withHost(ipv4"0.0.0.0")
      .withPort(port"8080")
      .withHttpApp(echo)
      .build // Resource[IO,Server]
      .useForever // IO[Nothing]
      .as(ExitCode.Success) // IO[ExitCode]
}
scala-cli Server.scala

SBT プロジェクトの場合

build.sbt
val V = new {
  val http4s = "1.0.0-M38"
}

lazy val server = project.in(file("."))
  .settings(
    scalaVersion := "3.2.1",
    libraryDependencies ++= Seq(
      "org.typelevel" %% "cats-effect" % "3.4.5"
    ) ++ Seq("core","dsl","ember-server").map( mod =>
      "org.http4s" %% s"http4s-$mod" % V.http4s
    )
  )
src/main/scala/Server.scala
import cats.effect._

import org.http4s.HttpRoutes
import com.comcast.ip4s._
import org.http4s.dsl.io._
import org.http4s.implicits._
import org.http4s.ember.server._


object Main extends IOApp {

    val echo = HttpRoutes.of[IO] {
        case GET -> Root / "echo" / arg => Ok(arg)
    }.orNotFound
    def run(args: List[String]):IO[ExitCode] = EmberServerBuilder
      .default[IO] // EmberServerBuilder[cats.effect.IO]
      .withHost(ipv4"0.0.0.0")
      .withPort(port"8080")
      .withHttpApp(echo)
      .build // Resource[IO,Server]
      .useForever // IO[Nothing]
      .as(ExitCode.Success) // IO[ExitCode]
}
sbt run

上のコードは SIGINT を受け取れない

SIGINT でサーバーを止めたい場合は以下のように書く

上のコードでは、SIGINT を受け取った後、Ember サーバーのデフォルトのシャットダウンタイムアウト時間 30 秒が経過するまで処理がブロックする.

詳しくは以下を参照.

https://blog.3qe.us/entry/2023/05/18/230159

Pro Tips: Scala Native で動かす

Linux / MacOS で HTTP サーバーを Scala Native で動かすことができる.

scala-cli package Server.sacla --native
// 非同期ランタイム
-//> using lib "org.typelevel::cats-effect:3.4.5"
+//> using lib "org.typelevel::cats-effect::3.4.5"
// http 関係
// http の基本型など
-//> using lib "org.http4s::http4s-core:1.0.0-M38"
+//> using lib "org.http4s::http4s-core::1.0.0-M38"
// ルーティング DSL など
-//> using lib "org.http4s::http4s-dsl:1.0.0-M38"
+//> using lib "org.http4s::http4s-dsl::1.0.0-M38"
// http サーバー
-//> using lib "org.http4s::http4s-ember-server:1.0.0-M38"
+//> using lib "org.http4s::http4s-ember-server::1.0.0-M38"
+//> using lib "com.armanbilge::epollcat::0.1.3"
+import elpollcat.EpollApp

- object Main extends IOApp
+ object Main extends EpollApp

trouble shooting

ld: library not found for -lcrypto

  • openssl がインスコされていることをチェック

https://zenn.dev/110416/articles/04d604b674badd

Discussion