Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
    k0ala
    @k0ala
    How should I specify the implicit params FileName and Line for castor actors?
    no implicit argument of type sourcecode.FileName was found for parameter fileName of method send in class BaseActor
    Simon Miles
    @drsimonmiles

    How should I specify the implicit params FileName and Line for castor actors?
    no implicit argument of type sourcecode.FileName was found for parameter fileName of method send in class BaseActor

    @k0ala That was the problem I raised above, I think. I fixed it (at least for compilation) by adding a dependency on a newer version of castor than the one used by cask, com.lihaoyi::castor:0.2.0

    k0ala
    @k0ala
    @drsimonmiles ah yes, thanks!
    k0ala
    @k0ala
    Does somebody have an example on how to configure cask to log with logback?
    Jared Neil
    @JaredNeil
    Is there an example or existing decorator like postJson, but that uses uPickle to parse to a case class? I'm thinking something like how you can set up MainArgs to parse to custom types.
    In use @jsonApi(TodoRoutes.getATodo) def aTodo(id: Int): Option[Todos] = { myDB.aTodo(id).headOption } which is a cask route... the decorator wraps the result into a response.
    Christian Ternus
    @ternus
    Hi! I'm trying to get the examples to work, but I'm running into this error:
    [$]> mill -w app.runBackground
    Compiling /Users/ternus/src/cask-0.7.12/example/minimalApplication/build.sc
    Cannot resolve app. Did you mean all?
    If I do mill resolve _, it shows:
    [$]> mill resolve _
    [1/1] resolve
    all
    clean
    inspect
    par
    path
    plan
    resolve
    show
    shutdown
    version
    visualize
    visualizePlan
    Pathikrit Bhowmick
    @pathikrit
    Is there a way to run cask server in watch mode using sbt? Something like sbt> ~server/runMain Server ? This will hot reload the server on code changes?
    2 replies
    kurgansoft
    @kurgansoft
    Is it possible to use Cask with livejs?
    The problem is that livejs emits head requests to check if a file has changed, but cask returns with a 405 error.
    Is there a simple way to enable head requests for static files(cask.staticFiles annotation)?
    jetaggart
    @jetaggart
    Hello, is there a way to install middleware with cask? I'm not seeing how I do something like CORS/logging easily. Sorry if I'm missing something obvious, cask looks perfect if I can just figure this out!
    Li Haoyi
    @lihaoyi
    you can use custom decorators for that
    jetaggart
    @jetaggart
    do you have an example by chance?
    I'm confused on how a decorator for a POST method, that receives a pre-flight check from the browser with a OPTIONS method can be handled by a decorator
    Li Haoyi
    @lihaoyi
    I don't think the decorators can have state spanning multiple requests
    you'll have to implement that out of band in your own code
    jetaggart
    @jetaggart
    gotcha, thank you!
    Objektwerks
    @objektwerks
    A Cask/Undertow server doesn't block in main. Why not?
    Is there a more elegant solution? What am I missing? Thanks in advance! :)
    Objektwerks
    @objektwerks
    Also, what is the suggested method of testing a Cask server. I have a few ideas , but would like to hear from the gurus. Thanks in advance!
    Li Haoyi
    @lihaoyi
    the cask examples/ folder projects have unit tests
    you can use that as a starting point and evolve the tests from there
    Objektwerks
    @objektwerks
    @lihaoyi Ok, I'll examine those examples more closely. Thanks!
    urbanchr
    @urbanchr

    I am trying to adapt the chatbot example from Hands-on-Scala to use some buttons and to modify a counter. At the moment I have

    @cask.get("/")
      def hello() = 
          doctype("html")(
          html(
            head(href := bootstrap, script(src := "/static/app2.js")), 
            body( 
                div(id := "messageList")(i(color.red)(cnt)),
                form(onsubmit := "submitForm(); return false")(
                    button(`type` := "submit", id := "nameInput",  value :="1")("1")
                    //button(`type` := "submit", id := "nameInput",  value :="2")("2")
                )
            )
          ))
    
      @cask.postJson("/")
      def postChatMsg(name: String) = {
        cnt = cnt + 1
        ujson.Obj("success" -> true, "txt" -> frag(i(color.red)(cnt)).render, "err" -> "oops")
      }

    However, when I uncomment the second button, I receive a 400 (Bad Request). The helper app2.js is as follows:

    function submitForm() {
      fetch(
        "/",
        {method: "POST", body: JSON.stringify({name: nameInput.value})}
      ).then(response => response.json())
       .then(json => {
          if (json["success"]) {
            messageList.innerHTML = json["txt"]
          }
      })
    }

    What is the right approach to get more than one button to work? Thanks a lot!

    Objektwerks
    @objektwerks
    What is the colloquial Cask way to build a route(s) that serves up 1) an index.html; and 2) associated resources from a Cask server's resource classpath? I've tried staticResources ("/") with no luck. I've used get("/") to manually classpath load an index.html, which works fine ... with 404 errors on all relative resources. This is pretty straightforward with Http4s and Akka-Http. TIA for any help!
    Li Haoyi
    @lihaoyi
    Have you looked at the examples? I'm pretty sure we have one that does what you deacribe
    Objektwerks
    @objektwerks
    Yes, thanks, I've poured all over the examples. I couldn't find a winning route combo that would 1) load an index.html and 2) load associated resources of the jvm classpath. I've come up with a manual hack to load resources - but the index.html doesn't really load correctly. I'll give it a go again today; and if that fails, I'll likely move my web assets to the js project in my classic Scalajs crossproject ( then I can deal with same origin headers ). Cheers! :)
    Objektwerks
    @objektwerks
    I looked at that yesterday; specifically:
    @cask.staticResources("/static")
      def static() = "todo"
    My resources are in /public/ I couldn't get anything to work. Also I don't understand the return value from def static().
    Currently I manually load index.html and associated resources. My index.html page loads correctly. All resources are loaded correctly less the ico and png files, which don't render in the browser. So I'm doing something wrong there.
    Objektwerks
    @objektwerks
    object Router extends LazyLogging:
      private val utf8 = Codec.UTF8.name
      private val contentType = "Content-Type"
      private val basePath = "/public/"
      private val indexHtml = loadResource("index.html")
      private val indexHtmlHeader = contentType -> "text/html; charset=UTF-8"
    
      def loadResource(resource: String): String =
        val path = s"$basePath$resource"
        logger.debug(s"*** load resource: $path")
        Using( Source.fromInputStream(getClass.getResourceAsStream(path), utf8) ) { 
          source => source.mkString
        }.getOrElse("")
    
      def toHeader(resource: String): (String, String) =
        logger.debug(s"*** to header: ${resource.split('.').last}")
        resource.split('.').last match
          case "css"  => contentType -> "text/css"
          case "ico"  => contentType -> "image/x-icon"
          case "png"  => contentType -> "image/png"
          case "js"   => contentType -> "text/javascript"
          case "map"  => contentType -> "application/json"
          case "html" => indexHtmlHeader
          case _      => contentType -> "text/plain"
    
    class Router(dispatcher: Dispatcher) extends Routes with LazyLogging:
      import Router._
    
      @cask.get("/")
      def index() = Response(indexHtml, 200, Seq(indexHtmlHeader))
    
      @cask.get(Router.basePath, subpath = true)
      def resources(request: Request) =
        val resource = request.remainingPathSegments.head
        val content = loadResource(resource)
        val headers = Seq(toHeader(resource))
        logger.debug(s"*** headers: $headers")
        Response(content, 200, headers)
    
      @cask.post("/command")
      def command(request: Request) =
        val command = read[Command](request.text())
        logger.debug(s"*** Command: $command")
    
        val event = dispatcher.dispatch(command)
        logger.debug(s"*** Event: $event")
        write[Event](event)
    
      initialize()
    Objektwerks
    @objektwerks
    Using cask.staticResources I attempted to recreate the above 1) index and 2) resources routes, but with no success.
    Objektwerks
    @objektwerks
    I added ImageIO code, so png files are loaded correctly now. I will use 12 Monkeys imageio library, tomorrow, to load the favicon.ico file. I'll keep you posted.
    Objektwerks
    @objektwerks
    Well I added the twelve monkeys dependency, which provides extended ImageIO support for ico and the like. So, now, I no longer get a NPE; yet the ico is not loaded by the browser correctly. I'm on an Apple M1. Here's the code:
    Objektwerks
    @objektwerks
    import cask.main.Routes
    import cask.model.{Request, Response}
    import com.typesafe.scalalogging.LazyLogging
    
    import java.awt.image.BufferedImage
    import java.io.ByteArrayOutputStream
    import javax.imageio.ImageIO
    
    import scala.io.{Codec, Source}
    import scala.util.{Try, Using}
    
    trait Resources(val basePath: String) extends LazyLogging:
      val utf8 = Codec.UTF8.name
      val contentType = "Content-Type"
      val indexHtml = loadResource("index.html")
      val indexHtmlHeader = contentType -> "text/html; charset=UTF-8"
    
      def toContentType(resource: String): String = resource.split('.').last
    
      def toPath(resource: String): String = s"$basePath$resource"
    
      def toHeader(resource: String): (String, String) =
        logger.debug(s"*** to header: ${toContentType(resource)}")
        toContentType(resource) match
          case "css"  => contentType -> "text/css"
          case "ico"  => contentType -> "image/x-icon"
          case "png"  => contentType -> "image/png"
          case "js"   => contentType -> "text/javascript"
          case "map"  => contentType -> "application/json"
          case "html" => indexHtmlHeader
          case _      => contentType -> "text/plain"
    
      def isImage(resource: String): Boolean =
        toContentType(resource) match
          case "ico" | "png"  => true
          case _              => false
    
      def loadResource(resource: String): Array[Byte] =
        val path = toPath(resource)
        logger.debug(s"*** load resource: $path")
        Using( Source.fromInputStream(getClass.getResourceAsStream(path), utf8) ) {
          source => source.mkString.getBytes
        }.getOrElse(Array.empty[Byte])
    
      def loadImage(resource: String): Array[Byte] =
        val path = toPath(resource)
        logger.debug(s"*** load image: $path")
        val url = getClass.getResource(path)
        val image = ImageIO.read(url)
        val baos = new ByteArrayOutputStream()
        val contentType = toContentType(resource)
        ImageIO.write(image, contentType, baos)
        baos.toByteArray
    
    class Router(dispatcher: Dispatcher) extends Routes with LazyLogging with Resources("/public/"):
      @cask.get("/")
      def index() = Response(indexHtml, 200, Seq(indexHtmlHeader))
    
      @cask.get(basePath, subpath = true)
      def resources(request: Request) =
        val resource = request.remainingPathSegments.head
        val headers = Seq(toHeader(resource))
        if isImage(resource) then Response(loadImage(resource), 200, headers)
        else Response(loadResource(resource), 200, headers)
    
      initialize()
    That's effectively what I was hoping cask.staticResources would do for me. Cheers!
    Objektwerks
    @objektwerks
    I corrected the favicon.ico loading error by replacing the true ico file with a png file --- still named favicon.ico, of course. :)
    Objektwerks
    @objektwerks
    FWIW, this project contains, among other examples, an updated Resources and ResourceRouter: https://github.com/objektwerks/cask
    Stewart Stewart
    @stewSquared

    Suppose I wanted to use a custom type in a path, like

    @cask.get("/user/:id")
    def user(id: java.util.UUID)

    Would it be appropriate to implement a custom cask.endpoints.PathReader[UUID]?
    Or is it better to parse an id string in the body and return a 400?

    Li Haoyi
    @lihaoyi
    either should work
    Objektwerks
    @objektwerks
    FYI, I've built a CorsHandler that works in initial tests. See:
    https://github.com/objektwerks/cask/blob/master/src/main/scala/objektwerks/handler/CorsHandler.scala
    https://github.com/objektwerks/cask/blob/master/src/main/scala/objektwerks/Server.scala
    Naturally, this can be built multiple ways. Note how a CorsHandler is initialized in Server, which extends cask.Main.
    I've posted the above info to cask/github #31 should someone want to run with this initial effort. Cheers!
    discobaba
    @uncleweirdo_twitter
    the autowire project seemed a little bit awesome. Is there some way to get that kind of strong typing with cask?