Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make @postJson handle incoming JSON in a streaming manner, introduce @postJsonCached #123

Merged
merged 4 commits into from
May 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 5 additions & 14 deletions cask/src/cask/endpoints/JsonEndpoint.scala
Original file line number Diff line number Diff line change
Expand Up @@ -42,26 +42,17 @@ object JsonData extends DataCompanion[JsonData]{
}
}

class postJson(val path: String, override val subpath: Boolean = false)
class postJsonCached(path: String, subpath: Boolean = false) extends postJsonBase(path, subpath, true)
class postJson(path: String, subpath: Boolean = false) extends postJsonBase(path, subpath, false)
abstract class postJsonBase(val path: String, override val subpath: Boolean = false, cacheBody: Boolean = false)
extends HttpEndpoint[Response[JsonData], ujson.Value]{
val methods = Seq("post")
type InputParser[T] = JsReader[T]

def wrapFunction(ctx: Request,
delegate: Delegate): Result[Response.Raw] = {
def wrapFunction(ctx: Request, delegate: Delegate): Result[Response.Raw] = {
val obj = for{
str <-
try {
val boas = new ByteArrayOutputStream()
Util.transferTo(ctx.exchange.getInputStream, boas)
Right(new String(boas.toByteArray))
}
catch{case e: Throwable => Left(cask.model.Response(
"Unable to deserialize input JSON text: " + e + "\n" + Util.stackTraceString(e),
statusCode = 400
))}
json <-
try Right(ujson.read(str))
try Right(ujson.read(if (cacheBody) ctx.bytes else ctx.exchange.getInputStream))
catch{case e: Throwable => Left(cask.model.Response(
"Input text is invalid JSON: " + e + "\n" + Util.stackTraceString(e),
statusCode = 400
Expand Down
1 change: 1 addition & 0 deletions cask/src/cask/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ package object cask {
type staticFiles = endpoints.staticFiles
type staticResources = endpoints.staticResources
type postJson = endpoints.postJson
type postJsonCached = endpoints.postJsonCached
type getJson = endpoints.getJson
type postForm = endpoints.postForm
type options = endpoints.options
Expand Down
11 changes: 11 additions & 0 deletions example/formJsonPost/app/src/FormJsonPost.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,17 @@ object FormJsonPost extends cask.MainRoutes{
)
}

@cask.postJsonCached("/json-obj-cached")
def jsonEndpointObjCached(value1: ujson.Value, value2: Seq[Int], request: cask.Request) = {
ujson.Obj(
"value1" -> value1,
"value2" -> value2,
// `cacheBody = true` buffers up the body of the request in memory before parsing,
// giving you access to the request body data if you want to use it yourself
"body" -> request.text()
)
}

@cask.postForm("/form")
def formEndpoint(value1: cask.FormValue, value2: Seq[Int]) = {
"OK " + value1 + " " + value2
Expand Down
13 changes: 13 additions & 0 deletions example/formJsonPost/app/test/src/ExampleTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,19 @@ object ExampleTests extends TestSuite{
)
ujson.read(response2.text()) ==> ujson.Obj("value1" -> true, "value2" -> ujson.Arr(3))


val response2Cached = requests.post(
s"$host/json-obj-cached",
data = """{"value1": true, "value2": [3]}"""
)
ujson.read(response2Cached.text()) ==>
ujson.Obj(
"value1" -> true,
"value2" -> ujson.Arr(3),
"body" -> """{"value1": true, "value2": [3]}"""
)


val response3 = requests.post(
s"$host/form",
data = Seq("value1" -> "hello", "value2" -> "1", "value2" -> "2")
Expand Down
1 change: 1 addition & 0 deletions example/httpMethods/build.sc
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ trait AppModule extends CrossScalaModule{
ivy"com.lihaoyi::utest::0.8.1",
ivy"com.lihaoyi::requests::0.8.0",
)
def forkArgs = Seq("--add-opens=java.base/java.net=ALL-UNNAMED")
}
}
Loading