feat(rest): Add common `serialization` utils
This commit is contained in:
parent
40543e3706
commit
d69a0206a7
|
@ -0,0 +1,87 @@
|
|||
import std/[strutils, algorithm, sets, strformat]
|
||||
import chronos, chronos/apps, chronos/unittest2/asynctests, stew/byteutils,
|
||||
metrics,
|
||||
nimcrypto
|
||||
import presto/[route, segpath, server, client]
|
||||
import json_serialization/std/[net, sets],
|
||||
json_serialization/stew/results as jsonSerializationResults,
|
||||
serialization, json_serialization
|
||||
|
||||
const ApplicationJsonMediaType* = MediaType.init("application/json")
|
||||
|
||||
createJsonFlavor RestJson
|
||||
|
||||
RestJson.useDefaultSerializationFor(
|
||||
auto
|
||||
)
|
||||
|
||||
type
|
||||
DecodeTypes* =
|
||||
auto
|
||||
|
||||
type
|
||||
EncodeTypes* =
|
||||
auto
|
||||
|
||||
proc encodeBytes*[T: EncodeTypes](value: T,
|
||||
contentType: string): RestResult[seq[byte]] =
|
||||
case contentType
|
||||
of "application/json":
|
||||
let data =
|
||||
block:
|
||||
try:
|
||||
var stream = memoryOutput()
|
||||
var writer = JsonWriter[RestJson].init(stream)
|
||||
writer.writeValue(value)
|
||||
stream.getOutput(seq[byte])
|
||||
except IOError:
|
||||
return err("Input/output error")
|
||||
except SerializationError:
|
||||
return err("Serialization error")
|
||||
ok(data)
|
||||
else:
|
||||
err("Content-Type not supported")
|
||||
|
||||
proc decodeBytes*[T: DecodeTypes](t: typedesc[T],
|
||||
value: openArray[byte],
|
||||
contentType: Opt[ContentTypeData]
|
||||
): RestResult[T] =
|
||||
|
||||
let mediaType =
|
||||
if contentType.isNone():
|
||||
ApplicationJsonMediaType
|
||||
else:
|
||||
if isWildCard(contentType.get().mediaType):
|
||||
return err("Incorrect Content-Type")
|
||||
contentType.get().mediaType
|
||||
|
||||
if mediaType == ApplicationJsonMediaType:
|
||||
try:
|
||||
ok RestJson.decode(value, T,
|
||||
requireAllFields = true,
|
||||
allowUnknownFields = true)
|
||||
except SerializationError as exc:
|
||||
debug "Failed to deserialize REST JSON data",
|
||||
err = exc.formatMsg("<data>"),
|
||||
data = string.fromBytes(value)
|
||||
err("Serialization error")
|
||||
else:
|
||||
err("Content-Type not supported")
|
||||
|
||||
proc decodeBody*[T](t: typedesc[T],
|
||||
body: ContentBody): Result[T, cstring] =
|
||||
if body.contentType != ApplicationJsonMediaType:
|
||||
return err("Unsupported content type")
|
||||
let data =
|
||||
try:
|
||||
RestJson.decode(body.data, T,
|
||||
requireAllFields = true,
|
||||
allowUnknownFields = true)
|
||||
except SerializationError as exc:
|
||||
debug "Failed to deserialize REST JSON data",
|
||||
err = exc.formatMsg("<data>"),
|
||||
data = string.fromBytes(body.data)
|
||||
return err("Unable to deserialize data")
|
||||
except CatchableError:
|
||||
return err("Unexpected deserialization error")
|
||||
ok(data)
|
Loading…
Reference in New Issue