טיפ סקאלה: שרת REST API פשוט עם cask

23/07/2024

הניסיון הראשון שלי לכתוב שרת API בסקאלה היה עם ספרייה בשם Tapir. טפיר מקסימה, יש לה המון תיעוד והרבה יכולות מתקדמות, אבל דווקא בדברים הפשוטים מצאתי פערים בתיעוד וגם בפונקציונאליות. המשך חיפושים הביא אותי לספריה בשם cask עליה אני רוצה לספר היום. אבל קודם הקוד:

package restapi
import cask._
import cask.model.{Request, Response}
import io.circe._
import io.circe.generic.auto._
import io.circe.syntax._
case class Demo(text: String)

object MyServer extends cask.MainRoutes {
  val JsonCorsHeaders: Seq[(String, String)] = Seq(
    "Content-Type" -> "application/json",
    "Access-Control-Allow-Origin" -> "*",
    "Access-Control-Allow-Methods" -> "GET, POST, PUT, DELETE, OPTIONS",
    "Access-Control-Allow-Headers" -> "Origin, X-Requested-With, Content-Type, Accept, Authorization"
  )

  @cask.options("/*")
  def options() = {
    cask.Response(
      "",
      headers = JsonCorsHeaders
    )
  }

  @cask.route("/", methods = Seq("get"))
  def hello() = {
    cask.Response(
      Demo("hello").asJson.toString,
      headers = JsonCorsHeaders
    )
  }


  initialize()
}

הקוד יצר אוביקט שאפשר להריץ אותו (לא צריך להוסיף לזה main או שום דבר), שמפעיל שרת ווב עם נתיב אחד - רק הנתיב הראשי, שמחזיר תמיד אוביקט JSON עם מפתח בשם text והערך hello. הוא מחזיר גם סט של כותרות שהגדרתי עבור CORS, ואם יהיו כמה נתיבים אפשר להשתמש באותו סט כותרות לכולם. בנוסף הקוד מגדיר טיפול גנרי למתודת OPTIONS, שוב בשביל ה CORS ששולחת רק את הכותרות כדי שדפדפנים יוכלו לקבל מידע משרת זה מכל דומיין.

בשביל להתקין את Cask יש להוסיף ל build.sbt את השורה:

libraryDependencies += "com.lihaoyi" %% "cask" % "0.9.1"

וכן אני יודע שהייתם כותבים כזה ב node.js, פייתון או רובי בעשר דקות. בסקאלה זה לקח לי שעתיים, בעיקר בגלל בעיות בתיעוד ויותר מדי ספריות של שרתי ווב. לכל שפה יש גם את החסרונות שלה.