mirror of
https://github.com/logos-messaging/logos-messaging-nim.git
synced 2026-01-03 22:43:09 +00:00
fix(rest): encode waku message payload in base64
This commit is contained in:
parent
cb3912fc64
commit
46de4fb3f6
@ -11,7 +11,7 @@ import
|
|||||||
libp2p/protocols/pubsub/pubsub
|
libp2p/protocols/pubsub/pubsub
|
||||||
import
|
import
|
||||||
../../waku/v2/node/wakunode2,
|
../../waku/v2/node/wakunode2,
|
||||||
../../waku/v2/node/rest/[server, client, utils],
|
../../waku/v2/node/rest/[server, client, base64, utils],
|
||||||
../../waku/v2/node/rest/relay/[api_types, relay_api, topic_cache]
|
../../waku/v2/node/rest/relay/[api_types, relay_api, topic_cache]
|
||||||
|
|
||||||
|
|
||||||
@ -164,8 +164,8 @@ suite "REST API - Relay":
|
|||||||
response.contentType == $MIMETYPE_JSON
|
response.contentType == $MIMETYPE_JSON
|
||||||
response.data.len == 3
|
response.data.len == 3
|
||||||
response.data.all do (msg: RelayWakuMessage) -> bool:
|
response.data.all do (msg: RelayWakuMessage) -> bool:
|
||||||
msg.payload == "TEST-1" and
|
msg.payload == Base64String.encode("TEST-1") and
|
||||||
string(msg.contentTopic.get()) == "content-topic-x" and
|
msg.contentTopic.get().string == "content-topic-x" and
|
||||||
msg.version.get() == Natural(1) and
|
msg.version.get() == Natural(1) and
|
||||||
msg.timestamp.get() == int64(2022)
|
msg.timestamp.get() == int64(2022)
|
||||||
|
|
||||||
@ -211,7 +211,7 @@ suite "REST API - Relay":
|
|||||||
discard await client.relayPostSubscriptionsV1(newTopics)
|
discard await client.relayPostSubscriptionsV1(newTopics)
|
||||||
|
|
||||||
let response = await client.relayPostMessagesV1(defaultTopic, RelayWakuMessage(
|
let response = await client.relayPostMessagesV1(defaultTopic, RelayWakuMessage(
|
||||||
payload: "TEST-PAYLOAD",
|
payload: Base64String.encode("TEST-PAYLOAD"),
|
||||||
contentTopic: some(ContentTopicString(defaultContentTopic)),
|
contentTopic: some(ContentTopicString(defaultContentTopic)),
|
||||||
timestamp: some(int64(2022))
|
timestamp: some(int64(2022))
|
||||||
))
|
))
|
||||||
|
|||||||
@ -1,12 +1,13 @@
|
|||||||
{.used.}
|
{.used.}
|
||||||
|
|
||||||
import std/typetraits
|
import
|
||||||
import chronicles,
|
|
||||||
unittest2,
|
|
||||||
stew/[results, byteutils],
|
stew/[results, byteutils],
|
||||||
|
chronicles,
|
||||||
|
unittest2,
|
||||||
json_serialization
|
json_serialization
|
||||||
import
|
import
|
||||||
../../waku/v2/node/rest/serdes,
|
../../waku/v2/node/rest/serdes,
|
||||||
|
../../waku/v2/node/rest/base64,
|
||||||
../../waku/v2/node/rest/relay/api_types
|
../../waku/v2/node/rest/relay/api_types
|
||||||
|
|
||||||
|
|
||||||
@ -15,25 +16,27 @@ suite "Relay API - serialization":
|
|||||||
suite "RelayWakuMessage - decode":
|
suite "RelayWakuMessage - decode":
|
||||||
test "optional fields are not provided":
|
test "optional fields are not provided":
|
||||||
# Given
|
# Given
|
||||||
let jsonBytes = toBytes("""{ "payload": "MESSAGE" }""")
|
let payload = Base64String.encode("MESSAGE")
|
||||||
|
let jsonBytes = toBytes("{\"payload\":\"" & $payload & "\"}")
|
||||||
|
|
||||||
# When
|
# When
|
||||||
let res = decodeFromJsonBytes(RelayWakuMessage, jsonBytes, requireAllFields = true)
|
let res = decodeFromJsonBytes(RelayWakuMessage, jsonBytes, requireAllFields = true)
|
||||||
|
|
||||||
# Then
|
# Then
|
||||||
require(res.isOk)
|
require(res.isOk())
|
||||||
let value = res.get()
|
let value = res.get()
|
||||||
check:
|
check:
|
||||||
value.payload == "MESSAGE"
|
value.payload == payload
|
||||||
value.contentTopic.isNone
|
value.contentTopic.isNone()
|
||||||
value.version.isNone
|
value.version.isNone()
|
||||||
value.timestamp.isNone
|
value.timestamp.isNone()
|
||||||
|
|
||||||
suite "RelayWakuMessage - encode":
|
suite "RelayWakuMessage - encode":
|
||||||
test "optional fields are none":
|
test "optional fields are none":
|
||||||
# Given
|
# Given
|
||||||
|
let payload = Base64String.encode("MESSAGE")
|
||||||
let data = RelayWakuMessage(
|
let data = RelayWakuMessage(
|
||||||
payload: "MESSAGE",
|
payload: payload,
|
||||||
contentTopic: none(ContentTopicString),
|
contentTopic: none(ContentTopicString),
|
||||||
version: none(Natural),
|
version: none(Natural),
|
||||||
timestamp: none(int64)
|
timestamp: none(int64)
|
||||||
@ -43,7 +46,7 @@ suite "Relay API - serialization":
|
|||||||
let res = encodeIntoJsonBytes(data)
|
let res = encodeIntoJsonBytes(data)
|
||||||
|
|
||||||
# Then
|
# Then
|
||||||
require(res.isOk)
|
require(res.isOk())
|
||||||
let value = res.get()
|
let value = res.get()
|
||||||
check:
|
check:
|
||||||
value == toBytes("""{"payload":"MESSAGE"}""")
|
value == toBytes("{\"payload\":\"" & $payload & "\"}")
|
||||||
|
|||||||
27
waku/v2/node/rest/base64.nim
Normal file
27
waku/v2/node/rest/base64.nim
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
{.push raises: [Defect].}
|
||||||
|
|
||||||
|
import stew/[results, byteutils, base64]
|
||||||
|
|
||||||
|
|
||||||
|
type Base64String* = distinct string
|
||||||
|
|
||||||
|
|
||||||
|
proc encode*(t: type Base64String, value: string|seq[byte]): Base64String =
|
||||||
|
let val = block:
|
||||||
|
when value is string:
|
||||||
|
toBytes(value)
|
||||||
|
else:
|
||||||
|
value
|
||||||
|
Base64String(base64.encode(Base64, val))
|
||||||
|
|
||||||
|
proc decode*(t: Base64String): Result[seq[byte], cstring] =
|
||||||
|
try:
|
||||||
|
ok(base64.decode(Base64, string(t)))
|
||||||
|
except:
|
||||||
|
err("failed to decode base64 string")
|
||||||
|
|
||||||
|
proc `$`*(t: Base64String): string {.inline.}=
|
||||||
|
string(t)
|
||||||
|
|
||||||
|
proc `==`*(lhs: Base64String|string, rhs: Base64String|string): bool {.inline.}=
|
||||||
|
string(lhs) == string(rhs)
|
||||||
@ -1,24 +1,25 @@
|
|||||||
{.push raises: [ Defect ].}
|
{.push raises: [Defect].}
|
||||||
|
|
||||||
import
|
import
|
||||||
std/[sets, strformat],
|
std/[sets, strformat],
|
||||||
stew/byteutils,
|
|
||||||
chronicles,
|
chronicles,
|
||||||
json_serialization,
|
json_serialization,
|
||||||
json_serialization/std/options,
|
json_serialization/std/options,
|
||||||
presto/[route, client, common]
|
presto/[route, client, common]
|
||||||
import ".."/serdes
|
import
|
||||||
import ../../wakunode2
|
../../../protocol/waku_message,
|
||||||
|
../serdes,
|
||||||
|
../base64
|
||||||
|
|
||||||
|
|
||||||
#### Types
|
#### Types
|
||||||
|
|
||||||
type
|
type
|
||||||
PubSubTopicString* = distinct string
|
PubSubTopicString* = distinct string
|
||||||
ContentTopicString* = distinct string
|
ContentTopicString* = distinct string
|
||||||
|
|
||||||
type RelayWakuMessage* = object
|
type RelayWakuMessage* = object
|
||||||
payload*: string
|
payload*: Base64String
|
||||||
contentTopic*: Option[ContentTopicString]
|
contentTopic*: Option[ContentTopicString]
|
||||||
version*: Option[Natural]
|
version*: Option[Natural]
|
||||||
timestamp*: Option[int64]
|
timestamp*: Option[int64]
|
||||||
@ -37,23 +38,29 @@ type
|
|||||||
|
|
||||||
proc toRelayWakuMessage*(msg: WakuMessage): RelayWakuMessage =
|
proc toRelayWakuMessage*(msg: WakuMessage): RelayWakuMessage =
|
||||||
RelayWakuMessage(
|
RelayWakuMessage(
|
||||||
payload: string.fromBytes(msg.payload),
|
payload: base64.encode(Base64String, msg.payload),
|
||||||
contentTopic: some(ContentTopicString(msg.contentTopic)),
|
contentTopic: some(ContentTopicString(msg.contentTopic)),
|
||||||
version: some(Natural(msg.version)),
|
version: some(Natural(msg.version)),
|
||||||
timestamp: some(msg.timestamp)
|
timestamp: some(msg.timestamp)
|
||||||
)
|
)
|
||||||
|
|
||||||
proc toWakuMessage*(msg: RelayWakuMessage, version = 0): WakuMessage =
|
proc toWakuMessage*(msg: RelayWakuMessage, version = 0): Result[WakuMessage, cstring] =
|
||||||
const defaultContentTopic = ContentTopicString("/waku/2/default-content/proto")
|
const defaultContentTopic = ContentTopicString("/waku/2/default-content/proto")
|
||||||
WakuMessage(
|
let
|
||||||
payload: msg.payload.toBytes(),
|
payload = ?msg.payload.decode()
|
||||||
contentTopic: ContentTopic(msg.contentTopic.get(defaultContentTopic)),
|
contentTopic = ContentTopic(msg.contentTopic.get(defaultContentTopic))
|
||||||
version: uint32(msg.version.get(version)),
|
version = uint32(msg.version.get(version))
|
||||||
timestamp: msg.timestamp.get(0)
|
timestamp = msg.timestamp.get(0)
|
||||||
)
|
|
||||||
|
ok(WakuMessage(payload: payload, contentTopic: contentTopic, version: version, timestamp: timestamp))
|
||||||
|
|
||||||
|
|
||||||
#### Serialization and deserialization
|
#### Serialization and deserialization
|
||||||
|
|
||||||
|
proc writeValue*(writer: var JsonWriter[RestJson], value: Base64String)
|
||||||
|
{.raises: [IOError, Defect].} =
|
||||||
|
writer.writeValue(string(value))
|
||||||
|
|
||||||
proc writeValue*(writer: var JsonWriter[RestJson], value: PubSubTopicString)
|
proc writeValue*(writer: var JsonWriter[RestJson], value: PubSubTopicString)
|
||||||
{.raises: [IOError, Defect].} =
|
{.raises: [IOError, Defect].} =
|
||||||
writer.writeValue(string(value))
|
writer.writeValue(string(value))
|
||||||
@ -74,6 +81,10 @@ proc writeValue*(writer: var JsonWriter[RestJson], value: RelayWakuMessage)
|
|||||||
writer.writeField("timestamp", value.timestamp)
|
writer.writeField("timestamp", value.timestamp)
|
||||||
writer.endRecord()
|
writer.endRecord()
|
||||||
|
|
||||||
|
proc readValue*(reader: var JsonReader[RestJson], value: var Base64String)
|
||||||
|
{.raises: [SerializationError, IOError, Defect].} =
|
||||||
|
value = Base64String(reader.readValue(string))
|
||||||
|
|
||||||
proc readValue*(reader: var JsonReader[RestJson], value: var PubSubTopicString)
|
proc readValue*(reader: var JsonReader[RestJson], value: var PubSubTopicString)
|
||||||
{.raises: [SerializationError, IOError, Defect].} =
|
{.raises: [SerializationError, IOError, Defect].} =
|
||||||
value = PubSubTopicString(reader.readValue(string))
|
value = PubSubTopicString(reader.readValue(string))
|
||||||
@ -85,7 +96,7 @@ proc readValue*(reader: var JsonReader[RestJson], value: var ContentTopicString)
|
|||||||
proc readValue*(reader: var JsonReader[RestJson], value: var RelayWakuMessage)
|
proc readValue*(reader: var JsonReader[RestJson], value: var RelayWakuMessage)
|
||||||
{.raises: [SerializationError, IOError, Defect].} =
|
{.raises: [SerializationError, IOError, Defect].} =
|
||||||
var
|
var
|
||||||
payload = none(string)
|
payload = none(Base64String)
|
||||||
contentTopic = none(ContentTopicString)
|
contentTopic = none(ContentTopicString)
|
||||||
version = none(Natural)
|
version = none(Natural)
|
||||||
timestamp = none(int64)
|
timestamp = none(int64)
|
||||||
@ -100,7 +111,7 @@ proc readValue*(reader: var JsonReader[RestJson], value: var RelayWakuMessage)
|
|||||||
|
|
||||||
case fieldName
|
case fieldName
|
||||||
of "payload":
|
of "payload":
|
||||||
payload = some(reader.readValue(string))
|
payload = some(reader.readValue(Base64String))
|
||||||
of "contentTopic":
|
of "contentTopic":
|
||||||
contentTopic = some(reader.readValue(ContentTopicString))
|
contentTopic = some(reader.readValue(ContentTopicString))
|
||||||
of "version":
|
of "version":
|
||||||
|
|||||||
@ -7,9 +7,12 @@ import
|
|||||||
json_serialization,
|
json_serialization,
|
||||||
json_serialization/std/options,
|
json_serialization/std/options,
|
||||||
presto/[route, client, common]
|
presto/[route, client, common]
|
||||||
import ".."/[serdes, utils]
|
import
|
||||||
import ../../wakunode2
|
../../wakunode2,
|
||||||
import "."/[api_types, topic_cache]
|
../serdes,
|
||||||
|
../utils,
|
||||||
|
./api_types,
|
||||||
|
./topic_cache
|
||||||
|
|
||||||
logScope: topics = "rest_api_relay"
|
logScope: topics = "rest_api_relay"
|
||||||
|
|
||||||
@ -130,9 +133,11 @@ proc installRelayPostMessagesV1Handler*(router: var RestRouter, node: WakuNode)
|
|||||||
if reqResult.isErr():
|
if reqResult.isErr():
|
||||||
return RestApiResponse.badRequest()
|
return RestApiResponse.badRequest()
|
||||||
|
|
||||||
let message: RelayPostMessagesRequest = reqResult.get()
|
let resMessage = reqResult.value.toWakuMessage(version = 0)
|
||||||
|
if resMessage.isErr():
|
||||||
|
return RestApiResponse.badRequest()
|
||||||
|
|
||||||
if not (waitFor node.publish(pubSubTopic, message.toWakuMessage(version = 0)).withTimeout(futTimeout)):
|
if not (waitFor node.publish(pubSubTopic, resMessage.value).withTimeout(futTimeout)):
|
||||||
error "Failed to publish message to topic", topic=pubSubTopic
|
error "Failed to publish message to topic", topic=pubSubTopic
|
||||||
return RestApiResponse.internalServerError()
|
return RestApiResponse.internalServerError()
|
||||||
|
|
||||||
|
|||||||
@ -118,6 +118,7 @@ components:
|
|||||||
properties:
|
properties:
|
||||||
payload:
|
payload:
|
||||||
type: string
|
type: string
|
||||||
|
format: byte
|
||||||
contentTopic:
|
contentTopic:
|
||||||
$ref: '#/components/schemas/ContentTopic'
|
$ref: '#/components/schemas/ContentTopic'
|
||||||
version:
|
version:
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{.push raises: [Defect].}
|
{.push raises: [Defect].}
|
||||||
|
|
||||||
import std/typetraits
|
|
||||||
import
|
import
|
||||||
|
std/typetraits,
|
||||||
stew/results,
|
stew/results,
|
||||||
chronicles,
|
chronicles,
|
||||||
serialization,
|
serialization,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user