:point_up: Edit: @lihaoyi: Hi! I am new to Scala and have been looking everywhere for something like Flask in Scala and Cask seems like the best minimalistic option.
Is something like what the below code does possible in Cask and if so how can I implement it? Please help!
app = Flask(name)
@app.route("/get_emp_info", methods = ['POST'])
def get_employee_record():
input_data = json.loads(request.get_json())
out_data = input_data .to_dict(orient='records')
return jsonify(out_data)
if name == "main":
app.run(host='0.0.0.0', port=6123)
Even if you can provide some link that does something very close to this, that'd be helpful. I'd basically want to be able to run it as a Scala RESTful application.
request: cask.Request
How can we read this if it is a json? like in python requests.get_json()
You can access the request's body and give it to your JSON parser, for example
@cask.get("/")
def foo(req: cask.Request) = {
val json = upickle.default.read[ujson.Value](req.bytes)
...
}
However, there are more idiomatic ways to read JSON in cask. The two that come to mind are:
bytes
method is implemented right in the request class https://github.com/com-lihaoyi/cask/blob/master/cask/src/cask/model/Params.scala#L20
The cask documentatino suggests that a decorator could be used to automagically serialise responses as JSON.
"
but you could make it e.g. automatically serialize returned objects to JSON responses via your favorite library, or serialize
"
Now, I've gotten this far..
class writeToDoList(val path: String, val methods: Seq[String])
extends cask.HttpEndpoint[Seq[Todos], Seq[String]]{
def wrapFunction(ctx: cask.Request, delegate: Delegate) = {
delegate(Map()).map{num =>
cask.Response(upickle.default.write(num))
}
}
def wrapPathSegment(s: String) = Seq(s)
type InputParser[T] = cask.endpoints.QueryParamReader[T]
}
But obviously, the end goal is extends cask.HttpEndpoint[T, Seq[String]]
, unfortunately, I can't seem to get the implicit in scope.
The compiler says "implementation limitation, argument lists more than length 1 are ignored", if I try to add an implicit argument to the decorator class.
Any suggestions?
Otherwise, I'd have to write a decorator per return type :-/...
@cask.postForm("/upload")
def uploadFile(image: cask.FormFile) = {
image.fileName
}
scala> requests.post("http://localhost:8080/upload", data=java.nio.file.Paths.get("cat1.jpg"))
requests.RequestFailedException: Request to http://localhost:8080/upload failed with status code 400
Unable to parse form data: java.lang.NullPointerException: Cannot invoke "io.undertow.server.handlers.form.FormDataParser.parseBlocking()" because the return value of "io.undertow.server.handlers.form.FormParserFactory.createParser(io.undertow.server.HttpServerExchange)" is null
cask.FormFile
requires you to use the requests.MultiPart
data structure to upload, rather than a raw data =
data =
post, you can use https://github.com/com-lihaoyi/cask/blob/f3fd29a9206cee465812a80fe6bd04c6c63500c2/example/minimalApplication/app/src/MinimalApplication.scala#L9
localhost
vs 0.0.0.0
is something I'd expect non-scala-web-developers to know :)
hands-on-scala-js
; I'm still a bit burnt out writing hands-on-scala-programming
in 2019-2020 era, so not sure I'd be able to pick up a big project like that
hands-on-scala-js
when my curiosity was stronger, my standards were lower, and my non-work responsibilities were much fewer haha
cask.Request
as you suggested. Now I am struggling with the notion of "being logged in", i.e. only allowing users access if they have successfully entered their password. If you have any tutorial/example on this, I am all ears!
cabins
value is missing from the POST, then cask returns a 400 instead of calling this method with a None
for the cabins option.
Hello. I've been trying out Cask and got an HTTP server with a Scala.js front-end working without problems, and all seems great. I then wanted to try out Websockets but have got stuck. I tried copying verbatim the first example from the codebase as a starting point:
https://github.com/com-lihaoyi/cask/blob/master/example/websockets/app/src/Websockets.scala
but I get compilation errors.
case cask.Ws.Text("") => channel.send(cask.Ws.Close())
no implicit argument of type sourcecode.FileName was found for parameter fileName of method send in class BaseActor
From looking at the code, I understand that WsActor inherits from Castor's BaseActor (via SimpleActor) and the latter's send method requires an implicit sourcecode fileName and line. I don't understand what these could be in the context of Websockets (but I'm quite new to Websockets).
I tried running the websockets example test from the Cask codebase, in case it was something odd in my own setup, but hit another problem doing that. I think it's a separate Mill-related question so I'll omit details.
Any suggestion how I might be getting the compilation error above?
getRawParams
is no longer valid? https://com-lihaoyi.github.io/cask/#extending-endpoints-with-decorators