diff options
| author | Oskari Timperi <oskari.timperi@iki.fi> | 2018-04-29 13:43:51 +0300 |
|---|---|---|
| committer | Oskari Timperi <oskari.timperi@iki.fi> | 2018-04-29 13:45:36 +0300 |
| commit | dbbbe7ca4d07a2e724ce0201432d9e510154cb07 (patch) | |
| tree | 1bb216d81589b83263a005a170928d39e27c6f57 | |
| parent | 4982bff3c11d6f7ee5535223af2c64f2bfa23d3b (diff) | |
| download | nimtwirp-dbbbe7ca4d07a2e724ce0201432d9e510154cb07.tar.gz nimtwirp-dbbbe7ca4d07a2e724ce0201432d9e510154cb07.zip | |
Initial support for JSON request/response
| -rw-r--r-- | README.md | 2 | ||||
| -rw-r--r-- | nimtwirp/generator.nim | 39 | ||||
| -rw-r--r-- | nimtwirp/nimtwirp.nim | 17 |
3 files changed, 48 insertions, 10 deletions
@@ -15,7 +15,7 @@ See the `example` directory for an example. - [x] server generation from protobuf Service definition - [x] client generation from protobuf Service definition - [x] protobuf input/output -- [ ] json input/output +- [x] json input/output - [x] asynchronous server - [x] synchronous client - [x] can serve multiple services easily (see [examples/multiservice](examples/multiservice)) diff --git a/nimtwirp/generator.nim b/nimtwirp/generator.nim index e3f94b2..1ad9b96 100644 --- a/nimtwirp/generator.nim +++ b/nimtwirp/generator.nim @@ -54,7 +54,7 @@ proc new{service.name}*(): {service.name} = new(result) proc handleRequest*(service: {service.name}, req: Request): Future[nimtwirp.Response] {{.async.}} = - let (_, methodName) = validateRequest(req, {service.name}Prefix) + let (contentType, methodName) = validateRequest(req, {service.name}Prefix) """ @@ -64,9 +64,20 @@ proc handleRequest*(service: {service.name}, req: Request): Future[nimtwirp.Resp ifel = "elif" result &= &""" {ifel} methodName == "{meth.name}": - let inputMsg = new{meth.inputType}(req.body) + var inputMsg: {meth.inputType} + + if contentType == "application/protobuf": + inputMsg = new{meth.inputType}(req.body) + elif contentType == "application/json": + let node = parseJson(req.body) + inputMsg = parse{meth.inputType}(node) + let outputMsg = await {meth.name}(service, inputMsg) - return nimtwirp.newResponse(serialize(outputMsg)) + + if contentType == "application/protobuf": + return nimtwirp.newResponse(serialize(outputMsg)) + elif contentType == "application/json": + return nimtwirp.newResponse(toJson(outputMsg)) """ result &= &""" @@ -81,10 +92,15 @@ proc genClient(service: Service, prefix: string): string = type {service.name}Client* = ref object of nimtwirp.Client -proc new{service.name}Client*(address: string): {service.name}Client = +proc new{service.name}Client*(address: string, kind = ClientKind.Protobuf): {service.name}Client = new(result) result.client = newHttpClient() - result.client.headers = newHttpHeaders({{"Content-Type": "application/protobuf"}}) + 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 """ @@ -92,9 +108,18 @@ proc new{service.name}Client*(address: string): {service.name}Client = for meth in service.methods: result &= &""" proc {meth.name}*(client: {service.name}Client, req: {meth.inputType}): {meth.outputType} = - let body = serialize(req) + var body: string + case client.kind + of ClientKind.Protobuf: + body = serialize(req) + of ClientKind.Json: + body = $toJson(req) let resp = request(client, {service.name}Prefix, "{meth.name}", body) - result = new{meth.outputType}(resp.body) + case client.kind + of ClientKind.Protobuf: + result = new{meth.outputType}(resp.body) + of ClientKind.Json: + result = parse{meth.outputType}(parseJson(resp.body)) """ diff --git a/nimtwirp/nimtwirp.nim b/nimtwirp/nimtwirp.nim index f3fa29d..242e2f1 100644 --- a/nimtwirp/nimtwirp.nim +++ b/nimtwirp/nimtwirp.nim @@ -23,6 +23,11 @@ type Client* = ref object of RootObj client*: HttpClient address*: string + kind*: ClientKind + + ClientKind* {.pure.} = enum + Protobuf + Json proc respond*(req: asynchttpserver.Request, resp: nimtwirp.Response): Future[void] = req.respond(resp.code, resp.body, resp.headers) @@ -46,6 +51,13 @@ proc newResponse*(body: string): nimtwirp.Response = result.body = body result.headers = newHttpHeaders({"Content-Type": "application/protobuf"}) +proc newResponse*(node: JsonNode): nimtwirp.Response = + new(result) + result.code = Http200 + result.body = newStringOfCap(512) + toUgly(result.body, node) + result.headers = newHttpHeaders({"Content-Type": "application/json"}) + proc handleHttpRequest(request: asynchttpserver.Request, handler: ServeHandlerProc) {.async.} = var fut = handler(request) @@ -124,9 +136,10 @@ proc validateRequest*(request: asynchttpserver.Request, prefix: string): tuple[c result.contentType = getOrDefault(request.headers, "Content-Type") - if result.contentType != "application/protobuf": + if result.contentType != "application/protobuf" and + result.contentType != "application/json": raise newTwirpError(TwirpInternal, - "expected Content-Type to be application/protobuf instead of " & + "expected Content-Type to be application/protobuf or application/json instead of " & result.contentType) if not startsWith(request.url.path, prefix): |
