DispatchTrie[Map[String, …]]
. It's the old structure inverted basically.
Hi! I am new to both Scala and Cask. I am creating a small solution using Cask to run on a local machine and need a way to start and stop the server on an ad-hoc basis.
Based on the examples in the Cask documentation, it seems that Cask is designed to always start automatically (either by extending cask.MainRoutes with the route definitions or extending cask.Main to include multiple route definitions).
Is there a way I can embed Cask into an application, from which I can control starting and stopping it as required?
: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!