London, 2022
scala
haskell
typescript
agda
--> data sent to Server
<-- data sent to ClientBasic request:
--> {
"jsonrpc":"2.0",
"method":"subtract",
"params":[
42,
23
],
"id":1
}
<-- {"jsonrpc": "2.0", "result": 19, "id": 1}https://www.jsonrpc.org/specification
--> data sent to Server
<-- data sent to ClientBasic request:
--> {
"jsonrpc":"2.0",
"method":"subtract",
"params":[
42,
23
],
"id":1
}
<-- {"jsonrpc": "2.0", "result": 19, "id": 1}https://www.jsonrpc.org/specification
--> data sent to Server
<-- data sent to ClientBasic request:
--> {
"jsonrpc":"2.0",
"method":"subtract",
"params":[
42,
23
],
"id":1
}
<-- {"jsonrpc": "2.0", "result": 19, "id": 1}https://www.jsonrpc.org/specification
--> data sent to Server
<-- data sent to ClientBasic request:
--> {
"jsonrpc":"2.0",
"method":"subtract",
"params":[
42,
23
],
"id":1
}
<-- {"jsonrpc": "2.0", "result": 19, "id": 1}https://www.jsonrpc.org/specification
--> data sent to Server
<-- data sent to ClientBasic request:
--> {
"jsonrpc":"2.0",
"method":"subtract",
"params":[
42,
23
],
"id":1
}
<-- {"jsonrpc": "2.0", "result": 19, "id": 1}https://www.jsonrpc.org/specification
--> data sent to Server
<-- data sent to ClientBasic request:
--> {
"jsonrpc":"2.0",
"method":"subtract",
"params":[
42,
23
],
"id":1
}
<-- {"jsonrpc": "2.0", "result": 19, "id": 1}https://www.jsonrpc.org/specification
--> data sent to Server
<-- data sent to ClientBasic request:
--> {
"jsonrpc":"2.0",
"method":"subtract",
"params":[
42,
23
],
"id":1
}
<-- {"jsonrpc": "2.0", "result": 19, "id": 1}https://www.jsonrpc.org/specification
--> data sent to Server
<-- data sent to ClientBasic request:
--> {
"jsonrpc":"2.0",
"method":"subtract",
"params":[
42,
23
],
"id":1
}
<-- {"jsonrpc": "2.0", "result": 19, "id": 1}https://www.jsonrpc.org/specification
--> data sent to Server
<-- data sent to ClientRequest with named parameters:
--> {
"jsonrpc":"2.0",
"method":"subtract",
"params":{
"subtrahend":23,
"minuend":42
},
"id":3
}
<-- {"jsonrpc": "2.0", "result": 19, "id": 1}https://www.jsonrpc.org/specification
--> data sent to Server
<-- data sent to ClientA notification:
--> {
"jsonrpc":"2.0",
"method":"subtract",
"params":{
"subtrahend":23,
"minuend":42
}
}https://www.jsonrpc.org/specification
--> data sent to Server
<-- data sent to ClientBatch request:
--> [
{"jsonrpc": "2.0", "method": "sum", "params": [1,2,4], "id": "1"},
{"jsonrpc": "2.0", "method": "subtract", "params": [42,23], "id": "2"},
]
<-- [
{"jsonrpc": "2.0", "result": 7, "id": "1"},
{"jsonrpc": "2.0", "result": 19, "id": "2"},
]https://www.jsonrpc.org/specification
--> data sent to Server
<-- data sent to ClientBatch request with a notification:
--> [
{"jsonrpc": "2.0", "method": "sum", "params": [1,2,4], "id": "1"},
{"jsonrpc": "2.0", "method": "notify_hello", "params": ["hello"]},
]
<-- [
{"jsonrpc": "2.0", "result": 7, "id": "1"},
]https://www.jsonrpc.org/specification
Why just not use tapir?
HTTP POST /
{
"jsonrpc":"2.0",
"method":"subtract",
"params":[
42,
23
],
"id":1
}
HTTP POST /
{
"jsonrpc":"2.0",
"method":"sum",
"params":[
42,
23
],
"id":1
}Why just not use tapir?
HTTP POST /
{
"jsonrpc":"2.0",
"method":"subtract",
"params":[
42,
23
],
"id":1
}
HTTP POST /
{
"jsonrpc":"2.0",
"method":"sum",
"params":[
42,
23
],
"id":1
}val jsonRpc = endpointWhy just not use tapir?
HTTP POST /
{
"jsonrpc":"2.0",
"method":"subtract",
"params":[
42,
23
],
"id":1
}
HTTP POST /
{
"jsonrpc":"2.0",
"method":"sum",
"params":[
42,
23
],
"id":1
}val jsonRpc = endpoint.postWhy just not use tapir?
HTTP POST /
{
"jsonrpc":"2.0",
"method":"subtract",
"params":[
42,
23
],
"id":1
}
HTTP POST /
{
"jsonrpc":"2.0",
"method":"sum",
"params":[
42,
23
],
"id":1
}val jsonRpc = endpoint.post.in(jsonBody[JsonRpcRequest])Why just not use tapir?
HTTP POST /
{
"jsonrpc":"2.0",
"method":"subtract",
"params":[
42,
23
],
"id":1
}
HTTP POST /
{
"jsonrpc":"2.0",
"method":"sum",
"params":[
42,
23
],
"id":1
}val jsonRpc = endpoint.post.in(jsonBody[JsonRpcRequest])
.out(jsonBody[Option[JsonRpcResponse]])Why just not use tapir?
HTTP POST /
{
"jsonrpc":"2.0",
"method":"subtract",
"params":[
42,
23
],
"id":1
}
HTTP POST /
{
"jsonrpc":"2.0",
"method":"sum",
"params":[
42,
23
],
"id":1
}Endpoint[JsonRpcRequest, JsonRpcError, Option[JsonRpcResponse]]Why just not use tapir?
https://github.com/softwaremill/tapir/issues/621
Declarative, type-safe json-rpc endpoints library
Basic request:
--> {
"jsonrpc":"2.0",
"method":"subtract",
"params":[
42,
23
],
"id":1
}
<-- {
"jsonrpc":"2.0",
"result":19,
"id":1
} Basic request:
--> {
"jsonrpc":"2.0",
"method":"subtract",
"params":[
42,
23
],
"id":1
}
<-- {
"jsonrpc":"2.0",
"result":19,
"id":1
}val subtract =
jsonRpcEndpoint(m"subtract")
Basic request:
--> {
"jsonrpc":"2.0",
"method":"subtract",
"params":[
42,
23
],
"id":1
}
<-- {
"jsonrpc":"2.0",
"result":19,
"id":1
}val subtract =
jsonRpcEndpoint(m"subtract")
.in(
param[Int]("subtrahend")
)Basic request:
--> {
"jsonrpc":"2.0",
"method":"subtract",
"params":[
42,
23
],
"id":1
}
<-- {
"jsonrpc":"2.0",
"result":19,
"id":1
}val subtract =
jsonRpcEndpoint(m"subtract")
.in(
param[Int]("subtrahend")
.and(param[Int]("minuend"))
)Basic request:
--> {
"jsonrpc":"2.0",
"method":"subtract",
"params":[
42,
23
],
"id":1
}
<-- {
"jsonrpc":"2.0",
"result":19,
"id":1
}val subtract =
jsonRpcEndpoint(m"subtract")
.in(
param[Int]("subtrahend")
.and(param[Int]("minuend"))
)
.out[Int]("result of the subtraction")Basic request:
--> {
"jsonrpc":"2.0",
"method":"subtract",
"params":[
42,
23
],
"id":1
}
<-- {
"jsonrpc":"2.0",
"result":19,
"id":1
}val subtract: JsonRpcEndpoint[(Int, Int), Unit, Int] =
jsonRpcEndpoint(m"subtract")
.in(
param[Int]("subtrahend")
.and(param[Int]("minuend"))
)
.out[Int]("result of the subtraction")Basic request:
--> {
"jsonrpc":"2.0",
"method":"subtract",
"params":[
42,
23
],
"id":1
}
<-- {
"jsonrpc":"2.0",
"result":19,
"id":1
}val subtract: JsonRpcServerEndpoint[Id] =
jsonRpcEndpoint(m"subtract")
.in(
param[Int]("subtrahend")
.and(param[Int]("minuend"))
)
.out[Int]("result of the subtraction")
.serverLogic[Id] { case (subtrahend, minuend) =>
Right(subtrahend - minuend)
}Request with named parameters:
--> {
"jsonrpc":"2.0",
"method":"subtract",
"params":{
"subtrahend":23,
"minuend":42
},
"id":3
}
<-- {
"jsonrpc":"2.0",
"result":19,
"id":1
}val subtract: JsonRpcServerEndpoint[Id] =
jsonRpcEndpoint(m"subtract")
.in(
param[Int]("subtrahend")
.and(param[Int]("minuend"))
)
.out[Int]("result of the subtraction")
.serverLogic[Id] { case (subtrahend, minuend) =>
Right(subtrahend - minuend)
}Request with named parameters:
--> {
"jsonrpc":"2.0",
"method":"subtract",
"params":{
"subtrahend":23,
"minuend":42
},
"id":3
}
<-- {
"jsonrpc":"2.0",
"result":19,
"id":1
}val subtract: JsonRpcServerEndpoint[Id] =
jsonRpcEndpoint(m"subtract", ParamStructure.ByName)
.in(
param[Int]("subtrahend")
.and(param[Int]("minuend"))
)
.out[Int]("result of the subtraction")
.serverLogic[Id] { case (subtrahend, minuend) =>
Right(subtrahend - minuend)
}Notification:
--> {
"jsonrpc":"2.0",
"method":"subtract",
"params":{
"subtrahend":23,
"minuend":42
}
# no request id
}val subtract: JsonRpcServerEndpoint[Id] =
jsonRpcEndpoint(m"subtract")
.in(
param[Int]("subtrahend")
.and(param[Int]("minuend"))
)
.out[Int]("result of the subtraction")
.serverLogic[Id] { case (subtrahend, minuend) =>
Right(subtrahend - minuend)
}Batch request:
-->[
{
"jsonrpc":"2.0",
"method":"subtract",
"params":[
42,
23
],
"id":1
},
{
"jsonrpc":"2.0",
"method":"subtract",
"params":[
42,
1
],
"id":2
}
]val subtract: JsonRpcServerEndpoint[Id] =
jsonRpcEndpoint(m"subtract")
.in(
param[Int]("subtrahend")
.and(param[Int]("minuend"))
)
.out[Int]("result of the subtraction")
.serverLogic[Id] { case (subtrahend, minuend) =>
Right(subtrahend - minuend)
}<-- [
{
"jsonrpc":"2.0",
"result":19,
"id":"1"
},
{
"jsonrpc":"2.0",
"result":41,
"id":"2"
}
]subtract: JsonRpcServerEndpoint[F[_]]sum: JsonRpcServerEndpoint[F[_]]greeting: JsonRpcServerEndpoint[F[_]]tapir
interperter
tapirEndpoint: ServerEndpoint[-R, F[_]]http4s
zio-http
netty
...
Endpoint[String, (Json, StatusCode), (Option[Json], StatusCode)]subtract: JsonRpcServerEndpoint[F[_]]sum: JsonRpcServerEndpoint[F[_]]greeting: JsonRpcServerEndpoint[F[_]]OpenRpc
interperter
openRpcSpecification: Either[Json, Yaml]subtract: JsonRpcServerEndpoint[F[_]]sum: JsonRpcServerEndpoint[F[_]]greeting: JsonRpcServerEndpoint[F[_]]Fs2
interperter
jsonRpcServer: fs2.Pipe[IO, String, Json]unix-domain-socket
websocket
Interceptor desing based on tapir's interceptors
Allow for customization on three different layers:
Armadillo
jsonRpcEndpoint
jsonRpcEndpoint
jsonRpcEndpoint
Custom Interceptor
legacyEndpoint
https://www.flaticon.com/free-icon/armadillo_4215064
https://github.com/input-output-hk/armadillo
https://github.com/ghostbuster91
https://github.com/softwaremill/tapir
kkondzielski