mirror of
https://github.com/vacp2p/research.git
synced 2025-02-22 19:28:34 +00:00
nim twirp service experiment
This commit is contained in:
parent
d7ab72bcbd
commit
85be50d903
@ -98,3 +98,7 @@ Actually use them, and check enum and dispatching etc.
|
||||
Put in Makefile
|
||||
|
||||
nimble install https://github.com/PMunch/protobuf-nim
|
||||
|
||||
### Protobuf service generation
|
||||
Install `nimtwirp`, then:
|
||||
`nimtwirp_build -I:. --out:. protocol.proto `
|
||||
|
237
remote_log/hello-twirp/protocol_pb.nim
Normal file
237
remote_log/hello-twirp/protocol_pb.nim
Normal file
@ -0,0 +1,237 @@
|
||||
# Generated by protoc_gen_nim. Do not edit!
|
||||
|
||||
import base64
|
||||
import intsets
|
||||
import json
|
||||
import strutils
|
||||
|
||||
import nimpb/nimpb
|
||||
import nimpb/json as nimpb_json
|
||||
|
||||
type
|
||||
vac_cas_CASRequest* = ref vac_cas_CASRequestObj
|
||||
vac_cas_CASRequestObj* = object of Message
|
||||
id: string
|
||||
vac_cas_CASResponse* = ref vac_cas_CASResponseObj
|
||||
vac_cas_CASResponseObj* = object of Message
|
||||
id: string
|
||||
data: string
|
||||
|
||||
proc newvac_cas_CASResponse*(): vac_cas_CASResponse
|
||||
proc newvac_cas_CASResponse*(data: string): vac_cas_CASResponse
|
||||
proc newvac_cas_CASResponse*(data: seq[byte]): vac_cas_CASResponse
|
||||
proc writevac_cas_CASResponse*(stream: Stream, message: vac_cas_CASResponse)
|
||||
proc readvac_cas_CASResponse*(stream: Stream): vac_cas_CASResponse
|
||||
proc sizeOfvac_cas_CASResponse*(message: vac_cas_CASResponse): uint64
|
||||
proc toJson*(message: vac_cas_CASResponse): JsonNode
|
||||
proc parsevac_cas_CASResponse*(obj: JsonNode): vac_cas_CASResponse
|
||||
|
||||
proc newvac_cas_CASRequest*(): vac_cas_CASRequest
|
||||
proc newvac_cas_CASRequest*(data: string): vac_cas_CASRequest
|
||||
proc newvac_cas_CASRequest*(data: seq[byte]): vac_cas_CASRequest
|
||||
proc writevac_cas_CASRequest*(stream: Stream, message: vac_cas_CASRequest)
|
||||
proc readvac_cas_CASRequest*(stream: Stream): vac_cas_CASRequest
|
||||
proc sizeOfvac_cas_CASRequest*(message: vac_cas_CASRequest): uint64
|
||||
proc toJson*(message: vac_cas_CASRequest): JsonNode
|
||||
proc parsevac_cas_CASRequest*(obj: JsonNode): vac_cas_CASRequest
|
||||
|
||||
proc fullyQualifiedName*(T: typedesc[vac_cas_CASResponse]): string = "vac.cas.CASResponse"
|
||||
|
||||
proc readvac_cas_CASResponseImpl(stream: Stream): Message = readvac_cas_CASResponse(stream)
|
||||
proc writevac_cas_CASResponseImpl(stream: Stream, msg: Message) = writevac_cas_CASResponse(stream, vac_cas_CASResponse(msg))
|
||||
proc toJsonvac_cas_CASResponseImpl(msg: Message): JsonNode = toJson(vac_cas_CASResponse(msg))
|
||||
proc fromJsonvac_cas_CASResponseImpl(node: JsonNode): Message = parsevac_cas_CASResponse(node)
|
||||
|
||||
proc vac_cas_CASResponseProcs*(): MessageProcs =
|
||||
result.readImpl = readvac_cas_CASResponseImpl
|
||||
result.writeImpl = writevac_cas_CASResponseImpl
|
||||
result.toJsonImpl = toJsonvac_cas_CASResponseImpl
|
||||
result.fromJsonImpl = fromJsonvac_cas_CASResponseImpl
|
||||
|
||||
proc newvac_cas_CASResponse*(): vac_cas_CASResponse =
|
||||
new(result)
|
||||
initMessage(result[])
|
||||
result.procs = vac_cas_CASResponseProcs()
|
||||
result.id = ""
|
||||
result.data = ""
|
||||
|
||||
proc clearid*(message: vac_cas_CASResponse) =
|
||||
message.id = ""
|
||||
|
||||
proc setid*(message: vac_cas_CASResponse, value: string) =
|
||||
message.id = value
|
||||
|
||||
proc id*(message: vac_cas_CASResponse): string {.inline.} =
|
||||
message.id
|
||||
|
||||
proc `id=`*(message: vac_cas_CASResponse, value: string) {.inline.} =
|
||||
setid(message, value)
|
||||
|
||||
proc cleardata*(message: vac_cas_CASResponse) =
|
||||
message.data = ""
|
||||
|
||||
proc setdata*(message: vac_cas_CASResponse, value: string) =
|
||||
message.data = value
|
||||
|
||||
proc data*(message: vac_cas_CASResponse): string {.inline.} =
|
||||
message.data
|
||||
|
||||
proc `data=`*(message: vac_cas_CASResponse, value: string) {.inline.} =
|
||||
setdata(message, value)
|
||||
|
||||
proc sizeOfvac_cas_CASResponse*(message: vac_cas_CASResponse): uint64 =
|
||||
if len(message.id) > 0:
|
||||
result = result + sizeOfTag(2, WireType.LengthDelimited)
|
||||
result = result + sizeOfString(message.id)
|
||||
if len(message.data) > 0:
|
||||
result = result + sizeOfTag(3, WireType.LengthDelimited)
|
||||
result = result + sizeOfString(message.data)
|
||||
result = result + sizeOfUnknownFields(message)
|
||||
|
||||
proc writevac_cas_CASResponse*(stream: Stream, message: vac_cas_CASResponse) =
|
||||
if len(message.id) > 0:
|
||||
protoWriteString(stream, message.id, 2)
|
||||
if len(message.data) > 0:
|
||||
protoWriteString(stream, message.data, 3)
|
||||
writeUnknownFields(stream, message)
|
||||
|
||||
proc readvac_cas_CASResponse*(stream: Stream): vac_cas_CASResponse =
|
||||
result = newvac_cas_CASResponse()
|
||||
while not atEnd(stream):
|
||||
let
|
||||
tag = readTag(stream)
|
||||
wireType = wireType(tag)
|
||||
case fieldNumber(tag)
|
||||
of 0:
|
||||
raise newException(InvalidFieldNumberError, "Invalid field number: 0")
|
||||
of 2:
|
||||
expectWireType(wireType, WireType.LengthDelimited)
|
||||
setid(result, protoReadString(stream))
|
||||
of 3:
|
||||
expectWireType(wireType, WireType.LengthDelimited)
|
||||
setdata(result, protoReadString(stream))
|
||||
else: readUnknownField(stream, result, tag)
|
||||
|
||||
proc toJson*(message: vac_cas_CASResponse): JsonNode =
|
||||
result = newJObject()
|
||||
if len(message.id) > 0:
|
||||
result["id"] = %message.id
|
||||
if len(message.data) > 0:
|
||||
result["data"] = %message.data
|
||||
|
||||
proc parsevac_cas_CASResponse*(obj: JsonNode): vac_cas_CASResponse =
|
||||
result = newvac_cas_CASResponse()
|
||||
var node: JsonNode
|
||||
if obj.kind != JObject:
|
||||
raise newException(nimpb_json.ParseError, "object expected")
|
||||
node = getJsonField(obj, "id", "id")
|
||||
if node != nil and node.kind != JNull:
|
||||
setid(result, parseString(node))
|
||||
node = getJsonField(obj, "data", "data")
|
||||
if node != nil and node.kind != JNull:
|
||||
setdata(result, parseString(node))
|
||||
|
||||
proc serialize*(message: vac_cas_CASResponse): string =
|
||||
let
|
||||
ss = newStringStream()
|
||||
writevac_cas_CASResponse(ss, message)
|
||||
result = ss.data
|
||||
|
||||
proc newvac_cas_CASResponse*(data: string): vac_cas_CASResponse =
|
||||
let
|
||||
ss = newStringStream(data)
|
||||
result = readvac_cas_CASResponse(ss)
|
||||
|
||||
proc newvac_cas_CASResponse*(data: seq[byte]): vac_cas_CASResponse =
|
||||
let
|
||||
ss = newStringStream(cast[string](data))
|
||||
result = readvac_cas_CASResponse(ss)
|
||||
|
||||
|
||||
proc fullyQualifiedName*(T: typedesc[vac_cas_CASRequest]): string = "vac.cas.CASRequest"
|
||||
|
||||
proc readvac_cas_CASRequestImpl(stream: Stream): Message = readvac_cas_CASRequest(stream)
|
||||
proc writevac_cas_CASRequestImpl(stream: Stream, msg: Message) = writevac_cas_CASRequest(stream, vac_cas_CASRequest(msg))
|
||||
proc toJsonvac_cas_CASRequestImpl(msg: Message): JsonNode = toJson(vac_cas_CASRequest(msg))
|
||||
proc fromJsonvac_cas_CASRequestImpl(node: JsonNode): Message = parsevac_cas_CASRequest(node)
|
||||
|
||||
proc vac_cas_CASRequestProcs*(): MessageProcs =
|
||||
result.readImpl = readvac_cas_CASRequestImpl
|
||||
result.writeImpl = writevac_cas_CASRequestImpl
|
||||
result.toJsonImpl = toJsonvac_cas_CASRequestImpl
|
||||
result.fromJsonImpl = fromJsonvac_cas_CASRequestImpl
|
||||
|
||||
proc newvac_cas_CASRequest*(): vac_cas_CASRequest =
|
||||
new(result)
|
||||
initMessage(result[])
|
||||
result.procs = vac_cas_CASRequestProcs()
|
||||
result.id = ""
|
||||
|
||||
proc clearid*(message: vac_cas_CASRequest) =
|
||||
message.id = ""
|
||||
|
||||
proc setid*(message: vac_cas_CASRequest, value: string) =
|
||||
message.id = value
|
||||
|
||||
proc id*(message: vac_cas_CASRequest): string {.inline.} =
|
||||
message.id
|
||||
|
||||
proc `id=`*(message: vac_cas_CASRequest, value: string) {.inline.} =
|
||||
setid(message, value)
|
||||
|
||||
proc sizeOfvac_cas_CASRequest*(message: vac_cas_CASRequest): uint64 =
|
||||
if len(message.id) > 0:
|
||||
result = result + sizeOfTag(2, WireType.LengthDelimited)
|
||||
result = result + sizeOfString(message.id)
|
||||
result = result + sizeOfUnknownFields(message)
|
||||
|
||||
proc writevac_cas_CASRequest*(stream: Stream, message: vac_cas_CASRequest) =
|
||||
if len(message.id) > 0:
|
||||
protoWriteString(stream, message.id, 2)
|
||||
writeUnknownFields(stream, message)
|
||||
|
||||
proc readvac_cas_CASRequest*(stream: Stream): vac_cas_CASRequest =
|
||||
result = newvac_cas_CASRequest()
|
||||
while not atEnd(stream):
|
||||
let
|
||||
tag = readTag(stream)
|
||||
wireType = wireType(tag)
|
||||
case fieldNumber(tag)
|
||||
of 0:
|
||||
raise newException(InvalidFieldNumberError, "Invalid field number: 0")
|
||||
of 2:
|
||||
expectWireType(wireType, WireType.LengthDelimited)
|
||||
setid(result, protoReadString(stream))
|
||||
else: readUnknownField(stream, result, tag)
|
||||
|
||||
proc toJson*(message: vac_cas_CASRequest): JsonNode =
|
||||
result = newJObject()
|
||||
if len(message.id) > 0:
|
||||
result["id"] = %message.id
|
||||
|
||||
proc parsevac_cas_CASRequest*(obj: JsonNode): vac_cas_CASRequest =
|
||||
result = newvac_cas_CASRequest()
|
||||
var node: JsonNode
|
||||
if obj.kind != JObject:
|
||||
raise newException(nimpb_json.ParseError, "object expected")
|
||||
node = getJsonField(obj, "id", "id")
|
||||
if node != nil and node.kind != JNull:
|
||||
setid(result, parseString(node))
|
||||
|
||||
proc serialize*(message: vac_cas_CASRequest): string =
|
||||
let
|
||||
ss = newStringStream()
|
||||
writevac_cas_CASRequest(ss, message)
|
||||
result = ss.data
|
||||
|
||||
proc newvac_cas_CASRequest*(data: string): vac_cas_CASRequest =
|
||||
let
|
||||
ss = newStringStream(data)
|
||||
result = readvac_cas_CASRequest(ss)
|
||||
|
||||
proc newvac_cas_CASRequest*(data: seq[byte]): vac_cas_CASRequest =
|
||||
let
|
||||
ss = newStringStream(cast[string](data))
|
||||
result = readvac_cas_CASRequest(ss)
|
||||
|
||||
|
112
remote_log/hello-twirp/protocol_twirp.nim
Normal file
112
remote_log/hello-twirp/protocol_twirp.nim
Normal file
@ -0,0 +1,112 @@
|
||||
import asyncdispatch
|
||||
import asynchttpserver
|
||||
import httpclient
|
||||
import json
|
||||
import strutils
|
||||
|
||||
import protocol_pb
|
||||
|
||||
import nimtwirp/nimtwirp
|
||||
import nimtwirp/errors
|
||||
|
||||
const
|
||||
CASPrefix* = "/twirp/vac.cas.CAS/"
|
||||
|
||||
type
|
||||
CAS* = ref CASObj
|
||||
CASObj* = object of RootObj
|
||||
GetImpl*: proc (service: CAS, param: vac_cas_CASRequest): Future[vac_cas_CASResponse] {.gcsafe, closure.}
|
||||
PostImpl*: proc (service: CAS, param: vac_cas_CASRequest): Future[vac_cas_CASResponse] {.gcsafe, closure.}
|
||||
|
||||
proc Get*(service: CAS, param: vac_cas_CASRequest): Future[vac_cas_CASResponse] {.async.} =
|
||||
if service.GetImpl == nil:
|
||||
raise newTwirpError(TwirpUnimplemented, "Get is not implemented")
|
||||
result = await service.GetImpl(service, param)
|
||||
|
||||
proc Post*(service: CAS, param: vac_cas_CASRequest): Future[vac_cas_CASResponse] {.async.} =
|
||||
if service.PostImpl == nil:
|
||||
raise newTwirpError(TwirpUnimplemented, "Post is not implemented")
|
||||
result = await service.PostImpl(service, param)
|
||||
|
||||
proc newCAS*(): CAS =
|
||||
new(result)
|
||||
|
||||
proc handleRequest*(service: CAS, req: Request): Future[nimtwirp.Response] {.async.} =
|
||||
let (contentType, methodName) = validateRequest(req, CASPrefix)
|
||||
|
||||
if methodName == "Get":
|
||||
var inputMsg: vac_cas_CASRequest
|
||||
|
||||
if contentType == "application/protobuf":
|
||||
inputMsg = newvac_cas_CASRequest(req.body)
|
||||
elif contentType == "application/json":
|
||||
let node = parseJson(req.body)
|
||||
inputMsg = parsevac_cas_CASRequest(node)
|
||||
|
||||
let outputMsg = await Get(service, inputMsg)
|
||||
|
||||
if contentType == "application/protobuf":
|
||||
return nimtwirp.newResponse(serialize(outputMsg))
|
||||
elif contentType == "application/json":
|
||||
return nimtwirp.newResponse(toJson(outputMsg))
|
||||
elif methodName == "Post":
|
||||
var inputMsg: vac_cas_CASRequest
|
||||
|
||||
if contentType == "application/protobuf":
|
||||
inputMsg = newvac_cas_CASRequest(req.body)
|
||||
elif contentType == "application/json":
|
||||
let node = parseJson(req.body)
|
||||
inputMsg = parsevac_cas_CASRequest(node)
|
||||
|
||||
let outputMsg = await Post(service, inputMsg)
|
||||
|
||||
if contentType == "application/protobuf":
|
||||
return nimtwirp.newResponse(serialize(outputMsg))
|
||||
elif contentType == "application/json":
|
||||
return nimtwirp.newResponse(toJson(outputMsg))
|
||||
else:
|
||||
raise newTwirpError(TwirpBadRoute, "unknown method")
|
||||
|
||||
|
||||
type
|
||||
CASClient* = ref object of nimtwirp.Client
|
||||
|
||||
proc newCASClient*(address: string, kind = ClientKind.Protobuf): CASClient =
|
||||
new(result)
|
||||
result.client = newHttpClient()
|
||||
result.kind = kind
|
||||
case kind
|
||||
of ClientKind.Protobuf:
|
||||
result.client.headers = newHttpHeaders({"Content-Type": "application/protobuf"})
|
||||
of ClientKind.Json:
|
||||
result.client.headers = newHttpHeaders({"Content-Type": "application/json"})
|
||||
result.address = address
|
||||
|
||||
proc Get*(client: CASClient, req: vac_cas_CASRequest): vac_cas_CASResponse =
|
||||
var body: string
|
||||
case client.kind
|
||||
of ClientKind.Protobuf:
|
||||
body = serialize(req)
|
||||
of ClientKind.Json:
|
||||
body = $toJson(req)
|
||||
let resp = request(client, CASPrefix, "Get", body)
|
||||
case client.kind
|
||||
of ClientKind.Protobuf:
|
||||
result = newvac_cas_CASResponse(resp.body)
|
||||
of ClientKind.Json:
|
||||
result = parsevac_cas_CASResponse(parseJson(resp.body))
|
||||
|
||||
proc Post*(client: CASClient, req: vac_cas_CASRequest): vac_cas_CASResponse =
|
||||
var body: string
|
||||
case client.kind
|
||||
of ClientKind.Protobuf:
|
||||
body = serialize(req)
|
||||
of ClientKind.Json:
|
||||
body = $toJson(req)
|
||||
let resp = request(client, CASPrefix, "Post", body)
|
||||
case client.kind
|
||||
of ClientKind.Protobuf:
|
||||
result = newvac_cas_CASResponse(resp.body)
|
||||
of ClientKind.Json:
|
||||
result = parsevac_cas_CASResponse(parseJson(resp.body))
|
||||
|
Loading…
x
Reference in New Issue
Block a user